使用可变长度参数进行Java重载

use*_*478 18 java overloading

为什么此代码中没有编译错误:

public class OverloadingVarArgs
{
    public void fun1(int... b)
    {
        System.out.println("int");
    }
    public void fun1(long... a)
    {
        System.out.println("long");
    }
    public static void main(String[] args)
    {
        OverloadingVarArgs obj = new OverloadingVarArgs();
        obj.fun1();
    }

}
Run Code Online (Sandbox Code Playgroud)

但是这段代码给出了编译错误!

public class OverloadingVarArgs
{
    public void fun1(int... b)
    {
        System.out.println("int");
    }
    public void fun1(boolean... a)
    {
        System.out.println("boolean");
    }
    public static void main(String[] args)
    {
        OverloadingVarArgs obj = new OverloadingVarArgs();
        obj.fun1();
    }
}
Run Code Online (Sandbox Code Playgroud)

我相信在这两种情况下应该存在编译错误,但事实并非如此.

chr*_*her 9

选择正确重载方法的规则如下:

  • 原始扩展使用可能的最小方法参数
  • 包装类型不能扩展到另一种包装类型
  • 您可以从int到Integer并将其扩展为Object但不包含Long
  • 加宽节拍拳击,拳击节拍Var-args.
  • 你可以Box然后加宽(一个int可以通过整数成为对象)
  • 你不能加宽然后Box(一个int不能变长)
  • 你不能将var-args与拓宽或装箱结合起来

看看最后一条规则.您不能将扩展或装箱与可变长度参数组合使用.这意味着不能以任何方式操纵类型,您必须按原样执行比较.int并且long可以比较,没有问题,编译器可以推断出int两者中较小的一个.根据第一条规则,它将寻找可能的最小方法参数,因此它已经计算出一个方法的正确(和唯一)路由.

但是,当你到booleanint,存在两个因为Java的之间没有比较法强类型.由于不知道哪种类型最小,编译器完全不知道你指的是哪种方法.

更多视觉示例

让我们从编译器的角度一步一步地看待它.首先,用intlong.

int和long

步骤1 - 检查参数是否与任何参数匹配,如果匹配,那么它与哪个参数完全匹配

好吧,varargs意味着你可以传递0给很多参数.在这种情况下,您已选择传递0参数,因此您的调用将匹配int类型和long类型.

第2步 - 尝试自动装箱或加宽.这应该有助于找出哪一个

您正在使用varargs,因此编译器知道它不能按照最终规则执行此操作.

第3步 - 尝试确定哪种类型最小

编译器能够将类型int与类型进行比较long.由此可知,它int是最小的类型.

第4步 - 拨打电话

使用int最小类型的知识,然后将值传递给执行方法.

好的,现在让我们用boolean和做同样的事情int.

boolean和int

步骤1 - 检查参数是否与任何参数匹配,如果匹配,那么它与哪个参数完全匹配

相同的故事.你没有通过任何东西,所以匹配两个参数.

第2步 - 尝试自动装箱或加宽.这应该有助于找出哪一个

如上所述,由于您使用了varargs,因此不允许这样做.

第3步 - 尝试确定哪种类型最小

这是至关重要的区别.这里的类型具有可比性.这意味着编译器不知道您希望通过参数最小类型调用哪个方法.因此,它无法找到正确的路线.

第4步 - 拨打电话

如果不知道要调用哪个方法,它就无法继续执行并抛出相应的异常.


Dun*_*nes 5

在第二个示例中,编译器无法确定要调用的最具体方法.

血淋淋的细节在语言规范中解释,但基本上如果比较两个变量(var-arg)方法,那么如果方法A可以接受传递给方法B的参数,而不是相反,那么方法B最具体.

在第一个示例中,应用了原始子类型规则,它们是:

double> 1 float

漂浮> 1

长> 1 int

int> 1个字符

int> 1

短> 1个字节

(其中> 1表示'直接超类型')

在这里,我们可以看到inta比a更具体long,因此fun1(int... b)选择了您的方法.

在第二个例子中,编译器在int和之间进行选择boolean.这些原始类型之间没有子类型关系,因此没有最具体的方法," 方法调用不明确,发生编译时错误. "(15.12.2.5中的最后一行).


Mar*_*oun 4

当你有intand long(可比较类型)时,默认情况下将使用最小的,这是int(因为你没有传递参数) - 我认为这是因为int 可以扩大到longlong不能(除非你明确地转换它),编译器将选择最低精度类型。

但是当你有boolean和 时int,就无法进行比较,你会得到

The method fun1(int[]) is ambiguous for the type OverloadingVarArgs
Run Code Online (Sandbox Code Playgroud)