【问题标题】:Why and How Does This Java Code Compile? [duplicate]为什么以及如何编译此 Java 代码? [复制]
【发布时间】:2016-07-11 11:36:59
【问题描述】:

以下代码打印“字符串”

public class Riddle {

    public static void main(String[] args) {
        hello(null);
    }

    public static void hello(Object o) {
        System.out.println("Object");
    }


    public static void hello(String s) {
        System.out.println("String");
    }

}

为什么该代码会编译? null 不是模棱两可吗?

例如,以下代码由于签名不明确而无法编译。

public class Riddle {

    public static void main(String[] args) {
        hello(null);
    }

    public static void hello(Object o) {
        System.out.println("Object");
    }

    public static void hello(Integer o) {
        System.out.println("Integer");
    }

    public static void hello(String s) {
        System.out.println("String");
    }

}

有人能解释一下为什么第一个示例可以编译而不会出现模棱两可的错误吗?

【问题讨论】:

  • null 只是一个参数。在第二种情况下,Object 方法签名无法针对其他两个进行解析。
  • 恭喜,我认为您已经找到了 Java 类型理论中的实际漏洞之一。一般来说,“Null”对于类型系统来说是一种奇怪的生物。如果您对此感兴趣,可以查看某些语言使用的 Option 类型...我个人认为这是一个非常好的功能,希望将其引入 Java 还为时不晚。

标签: java


【解决方案1】:

在第二种情况下不会编译,因为编译器无法在采用 Integer 的方法和采用 String 的方法之间做出决定,而在第一种情况下,编译器可以弄清楚。

参考:http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2

【讨论】:

    【解决方案2】:

    请见 JLS §15.12.2

    按照调用目的的方法解析顺序很重要 当存在相同类型的数据类型时,

    1. (对于原始数据类型)精确的数据类型匹配然后调用它。 1.1 如果没有,则调用更广泛的数据类型,然后调用它。
    2. 匹配数据类型的包装器类型或其父级,如果上述失败则匹配。
    3. 如果高于 2-failed,此数据类型的 Vararg 将匹配。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-16
      • 1970-01-01
      • 2015-09-15
      • 1970-01-01
      相关资源
      最近更新 更多