如果有add(int,long)
和add(long,int)
两种方法,则此类调用add(10,10)
将被视为含糊不清。
但是,如果我们有这样的例子,为什么它仍然被认为是歧义?
static void add(short num1, short num2) {
System.out.println("add(short, short)");
}
static void add(byte num1, long num2) {
System.out.println("add(byte, long)");
}
public static void main(String[] args) {
byte num1 = 10;
byte num2 = 10;
add(num1, num2);
}
我想知道编译器如何确定它是模棱两可的?虽然(在我看来)它不应该因为add(short, short)
需要两个类型提升步骤,而add(byte, long)
需要三个类型提升步骤..或者我是否有误解?
答案 0 :(得分:3)
请参阅8.4.9. Overloading - from the Java Language Specification和"overloading resolution procedure" - 特别是 15.12.2.5。选择最具体的方法。
如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符。 Java编程语言使用选择最具体方法的规则。
...
一个适用的方法m1 比另一个适用的方法m2更具体,用于参数表达式e1,...,ek,的调用,如果以下任何一个是真:
[..]
m2不是通用的,m1和m2适用于严格或松散的调用,其中m1具有形式参数类型S1,...,Sn和m2具有形式参数类型T1,...,Tn ,对于所有i(1≤i≤n,n = k),对于参数ei,Si的类型比Ti更具特异性。
[..]
...
有可能没有方法是最具体的,因为有两个或更多的方法是最具体的.. [有更多的规则具体/抽象..]
否则,方法调用不明确,并发生编译时错误。
Java编译器遵循这些规则;不同的语言将遵循不同的规则,并且人们在决定选择哪个重载时可能会发明自己的非Java规则。
对于选择更具体的方法,所有参数必须更具体。因此,示例案例在调用add(byte,byte)
时会导致模糊调用,因为:
add(short num1 /* less specific */, short num2 /* MORE specific */)
add(byte num1 /* MORE specific */, long num2 /* less specific */)
。但是,如果add(byte num1, long num2)
更改为add(byte num1, short num2)
,则会编译,因为:
add(short num1 /* less specific */, short num2 /* as specific */)
add(byte num1 /* MORE specific */, short num2 /* as specific */)
。基元之间的关系在4.10.1. Subtyping among Primitive Types中:long> int>简短>字节:
答案 1 :(得分:1)
将实际参数类型与方法参数列表匹配在两种情况下都需要类型强制,因此两者都不是“完美”匹配,因此不明确。如果你添加
static void add(byte num1, byte num2) {
System.out.println("add(byte, byte)");
}
这是一个完美的匹配,并没有歧义。