10

下面是具有 3 个重载构造函数的 java 类:

public class Test {

    public Test(Object i){
        System.out.println("Object invoked");
    }

    public Test(String i){
        System.out.println("String invoked");
    }

    public Test(int k){
        System.out.println("Integer invoked");
    }

    public static void main(String[] args) throws Exception {

        Test t = new Test(null);
    }
}

如果在创建类的新实例时传递了 null 值,将调用哪个构造函数?是什么原因 ?

4

2 回答 2

11

Java 总是选择适用于您传递的参数的最具体的方法(或构造函数)。在这种情况下,这就是String构造函数——StringObject.

想想如果你有会发生什么

new Test("some string")

theObjectString构造函数都适用于此毕竟,论点既是 anObject又是 a String但是,很明显String构造函数将被调用,因为它比Object构造函数更具体,并且在给定参数的情况下仍然适用。

null也不例外;这两个构造函数仍然适用,并且出于相同的原因String仍然选择构造函数。Object

现在,如果存在两个同样“特定”的构造函数(例如,如果你有一个Integer构造函数),当你调用Test(null).

这在JLS §15.12.2中有更详细的概述:

第二步在上一步中确定的类型中搜索成员方法。此步骤使用方法的名称和参数表达式的类型来定位可访问且适用的方法,即可以在给定参数上正确调用的声明。

可能有不止一种这样的方法,在这种情况下选择最具体的一种。最具体方法的描述符(签名加返回类型)是在运行时用于执行方法分派的描述符。

JLS §15.12.2.5中概述了确定哪种方法最具体的明确过程。

于 2013-09-14T15:02:05.290 回答
0

答案是:Test(String)被调用。

为什么?

在确定将调用一组重载方法中的哪一个时,Java 编译器将尝试匹配最具体的类型。它会在使用自动装箱之前首先尝试匹配签名。(@arshajii 提供了对 Java 语言规范的完美参考)

这里,Object是类型系统中最抽象的类。 String子类,Object因此更具体/具体。

这背后的逻辑是,如果您使用更具体的类型参数重载方法,您可能希望对该对象执行更多操作(当您创建子类时,通常会添加方法)。如果方法签名确定以另一种方式工作(即更抽象类型的签名获胜;这里,Test(Object)),那么将不会调用任何更具体的签名。

于 2013-09-14T15:20:52.750 回答