下面是一个例子:
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)
,因为这是最“具体”的:Test3
与Test2
相差一个类,String
与Object
相差一个类?
编译器返回reference to method1 is ambiguous
。
Java如何处理这种情况?
2条答案
按热度按时间chhkpiq41#
实际的调用是
Test 2对象引用上的适用方法有
对于第一个参数,类型Test 2,B是首选-Test 2比Test1更具体。
对于第二个参数,类型为String,首选A- String比Object更具体。
因此,A或B都不是明确选择的。解析需要一个对每个实际参数最具体的目标方法。
Java语言补充
ui7jx7zq2#
您可以参考www.example.com部分15.12.2.5了解所有这些是如何工作的。
在这个场景中,由于方法不是通用的,没有涉及到函数接口,所以可以忽略很多句子。对于像这样的简单情况,一个方法
m1
比另一个方法m2
更具体的条件归结为:(该节第二点)
m2
不是泛型,m1
和m2
可以通过严格或松散调用来应用,并且其中m1
具有形式参数类型S1
,...,Sn
,m2
具有形式参数类型T1
,...,Tn
,对于所有i(1 ≤ i ≤ n,n = k)的参数ei
,类型Si
比Ti
更具体。也就是说,
m1
中 every 参数的类型必须比m2
中相应的参数类型更具体。对于比另一个类型更具体的类型,Java只看是否有子类型关系。“有多远”并不重要。
对于任何表达式,如果S〈,则类型S比类型T更具体:T
现在您应该看到
method1(Test1, String)
并不比method1(Test2, Object)
更具体,因为Test1
并不比Test2
更具体。method1(Test2, Object)
也不比method1(Test1, String)
更具体,因为Object
不比String
更具体。然后规范继续说:
如果一个方法是可访问和可应用的,并且没有其他方法是可访问和可应用的,并且严格来说是更具体的,则该方法被称为最大限度地特定于方法调用。
如果只有一个最大的具体方法,那么这个方法实际上就是最具体的方法;它必须比任何其他可应用的可访问方法更具体。
在这种情况下,两个重载都是最大特定的。如果满足某些标准(下面进一步指定),则首选一些最大特定方法,但对于像这样的简单情况,它们不适用。
因此,编译器无法在这两个重载之间进行选择,并且调用是不明确的。