Java中最具体的重载方法规则是如何处理多个参数的?

f45qwnt8  于 2023-05-05  发布在  Java
关注(0)|答案(2)|浏览(80)

下面是一个例子:

class Driver {
    public static void main(String[] args) {
        Test1 t1 = new Test1();
        Test2 t2 = new Test2();
        Test3 t3 = new Test3();
        
        Object o = "";
        String s = "";
        
        t2.method1(t2, o); // calls method1 on Test1
        t2.method1(t3, s); // compile error: reference to method1 is ambiguous
    }
}

class Test1 {
    public void method1(Test2 v1, Object o) {
        System.out.println("Test1 called");
    }
}

class Test2 extends Test1 {
    public void method1(Test1 v1, String o) {
        System.out.println("Test2 called");
    }
}

class Test3 extends Test2 {
}

我有一个Test1类,它有子类Test2,它有子类Test3
我刚刚了解到,为了处理重载的方法,这些方法的参数通过某种is-a关系相互关联,java选择了 * 最具体的 * 方法。
我想测试当有多个参数时它是如何工作的。
第一个调用解析为Test1的实现,这是有意义的:对象不是String,因此Test2中的method1(Test1 v1, String o)不匹配。
但是对于第二个调用,t2.method1(t3, s)不应该解析为method1(Test2 v1, Object o),因为这是最“具体”的:Test3Test2相差一个类,StringObject相差一个类?
编译器返回reference to method1 is ambiguous
Java如何处理这种情况?

chhkpiq4

chhkpiq41#

实际的调用是

method1(Test3, String)

Test 2对象引用上的适用方法有

method1(Test1, String)   // A
 method1(Test2, Object)   // B

对于第一个参数,类型Test 2,B是首选-Test 2比Test1更具体。
对于第二个参数,类型为String,首选A- String比Object更具体。
因此,A或B都不是明确选择的。解析需要一个对每个实际参数最具体的目标方法。
Java语言补充

ui7jx7zq

ui7jx7zq2#

您可以参考www.example.com部分15.12.2.5了解所有这些是如何工作的。
在这个场景中,由于方法不是通用的,没有涉及到函数接口,所以可以忽略很多句子。对于像这样的简单情况,一个方法m1比另一个方法m2更具体的条件归结为:
(该节第二点)
m2不是泛型,m1m2可以通过严格或松散调用来应用,并且其中m1具有形式参数类型S1,...,Snm2具有形式参数类型T1,...,Tn,对于所有i(1 ≤ i ≤ n,n = k)的参数ei,类型SiTi更具体。
也就是说,m1every 参数的类型必须比m2中相应的参数类型更具体。
对于比另一个类型更具体的类型,Java只看是否有子类型关系。“有多远”并不重要。
对于任何表达式,如果S〈,则类型S比类型T更具体:T
现在您应该看到method1(Test1, String)并不比method1(Test2, Object)更具体,因为Test1并不比Test2更具体。
method1(Test2, Object)也不比method1(Test1, String)更具体,因为Object不比String更具体。
然后规范继续说:
如果一个方法是可访问和可应用的,并且没有其他方法是可访问和可应用的,并且严格来说是更具体的,则该方法被称为最大限度地特定于方法调用。
如果只有一个最大的具体方法,那么这个方法实际上就是最具体的方法;它必须比任何其他可应用的可访问方法更具体。
在这种情况下,两个重载都是最大特定的。如果满足某些标准(下面进一步指定),则首选一些最大特定方法,但对于像这样的简单情况,它们不适用。
因此,编译器无法在这两个重载之间进行选择,并且调用是不明确的。

相关问题