java认证考试的重载方法
我正在准备 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)与此订单。由于我们在第 1 步中,我们没有在寻找可变参数,我们不应该有匹配项。- 在这一步中,它执行装箱/拆箱。正如我们所做的那样
(int, Long),我希望结果是"int + Long"。 - 在这一步中,它还寻找可变参数,如果上一步不存在,它应该已经找到了
"int a, Var args long b".
我在这里缺少什么?我期待结果是"int + Long",但它是"int a, Var args long b"
编辑:代码取自Java SE 11 Developer 1Z0-819 OCP Course - Part 1作者命名的 Udemy 课程Tim Buchalka
回答
如果删除该方法,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)。
- Fun fact: when you write `Long l = 0L; var result = Calculator.add(1, true? 2: l);`, the `int` value `2` *can* be promoted to `long` and boxed to `Long` in one go. Even more mind-blowing, when you use `Long l = 0L; Integer i = 2; var result = Calculator.add(1, true? i: l);`, it is possible to unbox `i` from `Integer` to `int`, promote the value to `long` and box it to `Long`.