java 认证考试的重载方法

Overloaded methods for java certification exam

我正在准备 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-第一阶段执行重载决议,不允许装箱或拆箱转换,也不允许使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段

2- 第二阶段执行重载决议,同时允许装箱和拆箱,但仍然排除使用变量 arity 方法调用。如果在此阶段没有找到适用的方法,则处理继续到第三阶段。

3- 第三阶段允许重载与变量方法、装箱和拆箱相结合。

所以,根据这些规则,我认为这应该发生:

我在这里错过了什么?我期待结果是 "int + Long",但它是 "int a, Var args long b"

编辑:代码取自作者 Tim Buchalka

名为 Java SE 11 Developer 1Z0-819 OCP Course - Part 1 的 Udemy 课程

如果你删除方法 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).

重载适用性规则植根于 conversion 的规则(JLS Ch5,“Conversions and Contexts”。)有不同的 conversions 已定义(原始扩展(int 到 long)、装箱(int 到 Integer)、引用扩展(String 到 Object)等)。

在任何给定情况下,任何给定转换可能适用也可能不适用,具体取决于上下文。上下文包括赋值上下文、方法调用上下文、强制转换上下文等,重载决议第一阶段和后面阶段的区别是严格调用上下文的区别松散调用上下文.

让您困惑的可能是 add(int, Long) 不适用于 (int, int),即使在松散的调用上下文中也是如此。这是因为 (JLS 5.3) 扩展原始转换后跟装箱转换不是调用上下文中允许的转换之一。如果您调用 add(0, 0L) 它将适用(装箱转换)。

可变参数的情况适用于松散的上下文,因为存在从 intlong 的扩展原始转换。