为什么以及如何编译此Java代码?

为什么以及如何编译此Java代码?,java,Java,下面的代码打印“字符串” 那代码为什么要编译?空不是很含糊吗 例如,由于签名不明确,以下代码将无法编译 public class Riddle { public static void main(String[] args) { hello(null); } public static void hello(Object o) { System.out.println("Object"); } public stati

下面的代码打印“字符串”

那代码为什么要编译?空不是很含糊吗

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

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");
    }

}
有人能解释一下为什么第一个示例可以编译而没有不明确的错误吗?

请参见JLS

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

  • (对于基本数据类型)精确的数据类型匹配,然后调用它。 1.1如果没有,则调用更广泛的数据类型,然后调用该数据类型
  • 匹配数据类型的包装器类型或其父级,如果上述操作失败,则匹配
  • 如果上述2-2失败,则此数据类型的Vararg将匹配

  • 在第二种情况下,不编译,因为编译器无法在接受整数的方法和接受字符串的方法之间做出决定,而在第一种情况下,编译器可以找到它


    参考:

    null
    只是一个参数。在第二种情况下,
    对象
    方法签名无法与其他两个签名相比较。恭喜,我认为您已经发现了Java类型理论中的一个实际漏洞。一般来说,“空”是一种奇怪的生物类型系统。如果您对此感兴趣,可以查看某些语言使用的选项类型。。。我个人认为这是一个非常好的特性,希望将其引入Java不会太晚
    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");
        }
    
    }