我正在准备Java认证考试,但我不明白的一点是:
class Calculator {
public static long add(int a, long... b) {
System.out.println("int a, Var args long b");
int total = a;
for (long val : b) {
total += val;
}
return total;
}
public static long add(int a, Long b) {
System.out.println("int + Long");
return a + b;
}
}
public class OverloadTests {
public static void main(String[] args) {
var result = Calculator.add(1, 2);
System.out.println("result = " + result);
}
}Java文档(https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.12.2)说:
1-第一阶段执行重载解析,而不允许装箱或取消装箱转换,也不允许使用变量方法调用。如果在此阶段找不到适用的方法,则处理将继续到第二阶段。
2-第二阶段在允许装箱和取消装箱的同时执行过载解析,但仍然排除了变量方法调用的使用。如果在此阶段没有找到适用的方法,则处理将继续到第三阶段。
3-第三阶段允许重载与可变的方法、装箱和卸载相结合。
因此,有了这些规则,我认为这是应该发生的:
Calculator.add(1, 2);查找(int, int)签名,但未能找到。它还查找具有此顺序的(int, long)、(int, float)和(int, double)。因为我们在第一步,所以我们不是在寻找varargs,我们不应该有匹配。"int + Long"."int a, Var args long b".,它也会查找varargs,如果前面的步骤不存在,它应该已经找到了"int a, Var args long b".。
我在这漏掉了什么?我原以为结果是"int + Long",但它是"int a, Var args long b"
编辑:代码摘自作者Tim Buchalka的Udemy课程,名为Tim Buchalka。
发布于 2021-04-09 15:19:31
如果删除方法add(int a, long... b),您的代码将不会编译,因为其余的方法add(int a, Long b)无法与add(1, 2)一起调用,因为2是int,而基本int不能装箱到Long中。同样,语句Long a = 2;无效。因此,唯一匹配的候选是add(int a, long... b)。
发布于 2021-04-18 15:45:18
过载适用性的规则植根于转换规则(JLS Ch5,“反转和上下文”)。定义了不同的转换(原始扩展(int到long)、装箱(int到Integer)、引用扩展(String to Object)等等)。
在任何给定的情况下,根据上下文的不同,任何给定的转换都可能适用,也可能不适用。上下文包括赋值上下文、方法调用上下文、强制上下文等,重载解析的第一阶段与后期阶段的区别在于严格调用上下文与松散调用上下文之间的区别。
挂起您的可能是,即使在松散的调用上下文中,add(int, Long)也不适用于(int, int)。这是因为(JLS5.3)一个扩大的原语转换和一个装箱转换在调用上下文中不是允许的转换之一。如果您调用add(0, 0L),它将是适用的(装箱转换)。
varargs的情况适用于松散的上下文,因为从int到long的原始转换正在扩大。
https://stackoverflow.com/questions/67023762
复制相似问题