Varargs Java歧义调用


69

我对Java的varargs方法有些困惑:

public static int sum(int ...a) {
    return 0;
}

public static double sum(double ...a) {
    return 0.0;
}

当我尝试sum()不传递任何参数的情况下进行调用时,将int调用方法的版本。我不明白为什么;通常,编译器必须引发错误。

相比之下,当我尝试sum不带任何参数的情况下,以下代码会生成编译器错误:

public static int sum(int ...a) {
    return 0;
}

public static boolean sum(boolean ...a) {
    return true;
}

4
有趣的问题。
hmc_jake 2015年

1
您可以在这里找到问题的答案。
hmc_jake 2015年

Answers:


59

这里适用的一般规则是:如果一个方法签名严格比另一个方法签名更具体,则Java选择它时不会出错。

从直觉上讲,如果可以完全删除一个方法签名,则该方法签名更为具体,而另一个较不明确的方法签名则适用于每个现有调用。

当在签名sum(int... args)sum(double... args)签名之间进行选择时,签名sum(int... args)将更为具体,因为对该方法的任何调用也可以通过sum(double... args)应用扩展转换而传递给该签名。对于sum(boolean... args)不能进行类似转换的方法而言,情况并不相同。

Java语言规范,SE 8版本:

15.12。方法调用表达式

15.12.2.5。选择最具体的方法

Java编程语言使用选择最特定方法的规则。

...

如果满足以下任一条件,则使用参数表达式e1,...,ek进行调用时,一个适用的方法m1比另一适用的方法m2更具体:

...

  • m2不是通用的,并且m1和m2可通过严格调用或宽松调用来应用,并且m1具有形式参数类型S1,...,Sn,而m2具有形式参数类型T1,...,Tn,则Si类型更多对于所有i(1≤i≤n,n = k),自变量ei比Ti特定

...

如果S <:T(第4.10节),则对于任何表达式,类型S比类型T更具体。


4.10。子类型化

4.10.1。基本类型之间的子类型化

双> 1浮点

浮动> 1长

long> 1 int


7

本答案所述,选择使用哪种重载方法时要遵循规则。

去引用:

  1. 基本扩展使用可能的最小方法参数
  2. 包装器类型无法扩展为其他包装器类型
  3. 您可以将Box从int更改为Integer,然后将其扩展为Object,但不能将其扩展为Long
  4. 加宽节拍,搏击节拍可变参数。
  5. 您可以先装箱然后加宽(一个整数可以通过整数变成对象)
  6. 您不能先加宽然后再框(一个整数不能变长)
  7. 不能合并VAR-ARGS,有两个加宽拳击。

(让我们这样重新定义规则1:“原始扩展尽可能使用最具体的方法参数。”)

因此,牢记这些规则,我们可以了解这里发生的情况:

根据第一个规则,原始扩展尽可能使用最具体的方法参数。由于anint由非十进制数表示(例如1),而adouble由十进制数表示,其精度比a float(例如1.0)高32个字节,因此我们可以说ints“小于”或“小于” doubles,并且通过这种逻辑,int可以将s提升为doubles,并且double可以将s提升为ints。

简而言之,可以扩展到另一个原语(例如int-> float-> double)的原语比另一个更具体。例如,一个int更具体的double,因为1可以提升1.0

当您没有向同名的这些重载vararg方法传递任何参数时,由于返回实际上是相同的(分别为0和0.0),因此编译器会选择使用接受类型为vararg的方法,int因为它更具体

因此,然后,当您引入分别采用ints和booleans的相同方法(不能彼此扩展的类型)时,编译器现在无法选择要使用的方法,因为ints不能像ints一样被“提升”或“降级” ,floats和doubles。因此,它将引发编译错误。

我希望这可以帮助您了解正在发生的事情。


你似乎有doublefloat混合起来。所述JLS 8的呼叫的第5.1.2节floatdouble19中的一个“扩大原始转化”。您的答案暗示double可以扩大到float
Erick G. Hagstrom
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.