方法重载中的不明确问题

Abe*_*Abe 5 java

有人可以帮助解释为什么测试 2 和测试 3 有问题吗?

public static void main (String[] args) {
    byte b = 5;
    doCalc(b, b);
}
Run Code Online (Sandbox Code Playgroud)

测试1:这两种方法没有歧义问题。

static void doCalc(byte a, byte b) {
    System.out.print("byte, byte");
}
static void doCalc(Byte s1, Byte s2) {
    System.out.print("Byte, Byte");
}
Run Code Online (Sandbox Code Playgroud)

测试2:这两个方法没有编译时二义性,但存在运行时二义性。

static void doCalc(Byte... a) {
    System.out.print("byte 1...");
}
static void doCalc(long... a) {
    System.out.print("byte 2...");
}
Run Code Online (Sandbox Code Playgroud)

测试3:这两个方法在编译时存在二义性。

static void doCalc(Byte... a) {
    System.out.print("byte 1...");
}
static void doCalc(byte... a) {
    System.out.print("byte 2...");
}
Run Code Online (Sandbox Code Playgroud)

jac*_*271 2

第一种情况,不会出现错误,因为这两个方法的参数类型不同,并且不存在重载二义性。编译器可以根据调用期间传递的参数类型明确确定要调用哪个方法。

第二次和第三次测试怎么样,这里的一切都更有趣。如果该方法采用与原始类型相对应的可变参数,可变参数会自动将原始数据类型包装到其相应的包装类中。(byte...=>Byte...调用方法时)。

第二种情况,如果你调用doCalc(12, 1)例如,12and1被视为int字面量,但它可以自动转成long(int -> long)。因此该方法doCalc(long... a)有一个优点,因为它可以直接接受类型的参数(不能从到forlong转换,但可以从到),这是一个原始。intbyteint -> byte -> Byteintlonglong

我在这里得到下一个输出:byte 2...

但您可以按如下方式调用该方法:

byte b = 1; 
doCalc(b, b);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,会出现编译时错误,因为它可以转换byte -> int -> long,而且它也可以转换byte -> Byte

另外,您可以尝试以下方法:

static void doCalc(Long... a) {
    System.out.print("byte 2...");
}
Run Code Online (Sandbox Code Playgroud)

这里即使你调用doCalc(1, 1),也会出现编译时错误,因为它无法包装intLong.

第三种情况怎么样,你有两个非泛型方法(Byte...vs Byte...)。为了选择其中一种方法,其中一种方法必须比另一种方法更具体。在您的情况下,每个方法只有一个参数,并且为了其中一个比另一个更具体,该一个参数的类型必须是另一个方法参数的子类型。

由于byte不是 的子类型,Byte因此没有最具体的方法,并且编译器会抛出编译时错误。

看一下这个。JLS 15.12.2.5 选择最具体的方法:https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5

另外,请检查这些答案:

  1. Java 8 三元条件和未装箱原语的方法重载歧义
  2. 为什么这个方法重载不明确?