我已经读过在方法重载方面,优先级如下:
完全匹配>加宽>装箱/拆箱> varargs
这适用于只有一个参数的函数。但对于具有多个参数的函数,这有时会产生奇怪的结果,可能是因为我无法正确应用此规则。
例如:
代码1:
public static void overloadResolve(long i,int j){} //1
public static void overloadResolve(int i,Integer o){} //2
overloadResolve(5,6); // calls 1
代码2:
public static void overloadResolve(int i,int... j){} //1
public static void overloadResolve(Integer i,long o){} //2
overloadResolve(5,6); // calls 2
你能解释在重载的情况下如何处理多个参数函数吗?
答案 0 :(得分:2)
嗯,在第一种情况下,第一种方法有一个参数需要加宽,另一个参数完全匹配。第二种方法有一个完全匹配的参数,另一个需要装箱。由于加宽优先于拳击,因此选择第一种方法。
在第二种情况下,第一种方法有varargs,而第二种方法需要装箱和加宽。由于扩展和装箱优先于varargs,因此选择第二种方法。
您可以提供一些示例,其中不清楚选择哪种方法:
public static void overloadResolve(long i,Integer j){} //1
public static void overloadResolve(Integer i,long o){} //2
overloadResolve(5,6);
在这种情况下,第一个方法优先于第一个参数,而第二个方法优先于第二个参数。因此编译器无法在它们之间进行选择,编译也会失败。
答案 1 :(得分:1)
在你的第二种情况下,由于最后一个优先级是varargs,在此之前它将Auto Boxing(int转换为Integer-first参数)和Widening for second argument(int to long)。作为最后优先级的varargs,它选择call 2
。
答案 2 :(得分:1)
正如您所说,优先顺序是完全匹配>加宽>装箱/拆箱> varargs。以下是Java将为您做的事情:
public static void overloadResolve(long i,int j){} //1
public static void overloadResolve(int i,Integer o){} //2
overloadResolve(5,6);
overloadResolve(int, int)
所以没有完全匹配。int i
扩展为long i
匹配overloadResolve(long i,int j)
,让我们称之为!示例2:
public static void overloadResolve(int i,int... j){} //1
public static void overloadResolve(Integer i,long o){} //2
overloadResolve(5,6);
overloadResolve(int, int)
所以没有完全匹配。int i
扩展为long i
并将第一个arg int i
加入Integer i
匹配public static void overloadResolve(Integer i,long o)
,我们称之为!基本上,你可以为每个参数应用优先级顺序,直到它与其中一个重载的签名匹配。
答案 3 :(得分:1)
这里详细定义了Java中的重载方法选择过程:http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2和状态:
(...) uses the name of the method and the types of the argument expressions to
locate methods that are both accessible and applicable, that is,
declarations that can be correctly invoked on the given arguments.
There may be more than one such method, in which case the most specific one is chosen.
如果不深入细节,您案例中的陈述most specific one is chosen
可归结为:
1. For all parameters identify their respective priority in method signature (based on the order you've defined)
2. Choose lowest priority out of them for every method.
3. Method with the highest resulting priority will be applied.
让我们看看它对你所展示的代码有何用处:
overloadResolve(5,6); //Call with (int, int)
CODE1:
//(widening, exact) -> lowest priority: widening
public static void overloadResolve(long i,int j){}
//(exact, autoboxing) -> lowest priority: autoboxing
public static void overloadResolve(int i,Integer o){}
由于最高优先级正在扩大,因此选择第一种方法
CODE2:
//(exact, vararg) -> lowest: vararg
public static void overloadResolve(int i,int... j){}
//(autoboxing, widening) -> lowest: autoboxing
public static void overloadResolve(Integer i,long o){}
由于最高可用优先级正在扩大,因此选择第二种方法。