问题 Java如何使用相同的名称/签名区分这些多个方法?


我今天正在追踪一个错误,我发现其中一个类中有一些奇怪的东西。我删除尽可能多的代码在这里发布:

class A {
    static int obtainNumber() { return 42; }
    static int obtainNumber() { return 3; }
    static int obtainNumber() { return -1; }
    static {
        System.out.println(obtainNumber());
    }
}

这个类有3个方法,名称和签名完全相同。起初我以为这是无效代码,但是eclipse会突出显示红色代码。它确实有效:

javac A.java && java A
42
Exception in thread "main" java.lang.NoSuchMethodError: main

所以我想也许Java会使用它看到的第一个。我重新测试了:

class A {
    static int obtainNumber() { return 3; }
    static int obtainNumber() { return -1; }
    static int obtainNumber() { return 42; }
    static {
        System.out.println(obtainNumber());
    }
}

不,同样的结果:

javac A.java && java A
42
Exception in thread "main" java.lang.NoSuchMethodError: main

我想也许它使用的是42,因为它是最大的。为了测试这个,我拿了原始并更改了返回值:

class A {
    static int obtainNumber() { return 0; }
    static int obtainNumber() { return 1; }
    static int obtainNumber() { return 2; }
    static {
        System.out.println(obtainNumber());
    }
}

它仍然知道使用第一个:

javac A.java && java A
0
Exception in thread "main" java.lang.NoSuchMethodError: main

如果我再次对它们重新排序:

class A {
    static int obtainNumber() { return 1; }
    static int obtainNumber() { return 0; }
    static int obtainNumber() { return 2; }
    static {
        System.out.println(obtainNumber());
    }
}

相同的结果:

javac A.java && java A
0
Exception in thread "main" java.lang.NoSuchMethodError: main

我认为Java是一种基于文本的语言,我希望这种语言不可能。 Java如何跟踪哪种方法?


2168
2017-07-15 20:00


起源

如果你注意到,那个被采用的是具有与其他语法不同的语法的那个。也许这可能会基于隐藏的角色或语法怪癖来提示你。 - Andrey Akhmetov
为什么会有人这样做?这就像是程序员的魔术 - Shoe
来自蝙蝠侠黑暗骑士的@Jim: 有些男人只想看世界燃烧。 - Luiggi Mendoza
因此,我刚刚产生了许多糟糕的想法 - chancea
您应该检查项目是否存在编码问题,特别是如果它已从其他系统类型或较旧的存储介质中恢复,这些存储介质可能有故障或者已经暴露给携带瘟疫的传统设备。 - Andrey Akhmetov


答案:


隐藏的字符。源代码相当于

static int obtainNumber() { return 42; }

static int obtain\ ufeffNumber() { return 3; }

static int obtain\ ufeff \ ufeffNumber() { return -1; }

为了避免这种问题,我的源文件严格来说是US-ASCII。我想确定我看到的字符正是编译器看到的字符。


6
2017-07-15 20:58



让我觉得他故意这样做......
哇,我觉得上一个程序员有点心怀不满...... - Michael


我只是在我的IDE中复制/粘贴了这个,虽然这是一个奇迹,然后在尝试保存文件时出现错误消息清除此 问题

保存无法完成。如果问题仍然存在,请尝试文件>另存为...

原因:   某些字符无法使用“Cp1252”caracter编码进行映射。   更改编码或删除“Cp1252”caracter编码不支持的字符。

因此,这些方法不具有相同的名称,只使用看起来相同的字符。

有关Java源文件的字符编码的更多信息:


8
2017-07-15 20:04



@downvoter至少解释你的downvote理由。 - Luiggi Mendoza


我的 原版的 评论:

如果你注意到,那个被采用的是具有与其他语法不同的语法的那个。也许这可能会基于隐藏的角色或语法怪癖来提示你。

我将它粘贴到Eclipse中,并注意到了一些额外的字符。我把保存的文件(在CP1252中)扔到十六进制编辑器中,找到一个字节顺序标记。

当我看,CP1252没有字节顺序标记,但字符本身在CP1252中。可能已进入迷路unicode角色。

当我仔细观察时,另一种方法在另一个字节顺序中有另一个字节顺序标记。

他们是怎么来的,我们永远不会知道。但是,我们知道编译器正在使用它  字节顺序标记。

您应该检查项目是否存在编码问题,特别是如果它已从其他系统类型或可能有故障或已暴露给传统设备的旧存储介质中恢复。

我们真的需要通过meta处理这个FGITW行为 某时 现在。


1
2017-07-15 20:07