Varargs Java模糊呼叫

时间:2015-07-25 14:00:46

标签: java methods overloading variadic-functions

我对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;
}

2 个答案:

答案 0 :(得分:55)

这里适用的一般规则是:如果一个方法签名严格更具体,那么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. Choosing the Most Specific Method

     

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

     

...

     

对于带有参数表达式e1,...,ek的调用,如果满足以下任何条件,则一个适用的方法m1比另一个适用的方法m2更具体:

     

...

     
      
  • m2不是通用的,m1和m2适用于严格或松散调用,其中m1具有形式参数类型S1,...,Sn和m2具有形式参数类型T1,...,Tn,类型对于所有i(1≤i≤n,n = k),对于参数ei,Si比更具体。
  •   
     

...

     

如果S<:T(§4.10),则类型S比任何表达式的类型T更具特异性。

  

4.10。子类型

     

4.10.1. Subtyping among Primitive Types

     

double> 1 float

     

浮动> 1长

     

long> 1 int

答案 1 :(得分:7)

this answer中所述,在选择要使用的重载方法时会遵循规则。

引用:

  
      
  1. 原始扩展使用可能的最小方法参数
  2.   
  3. 包装类型不能加宽到另一种包装类型
  4.   
  5. 您可以从int到Integer并将其扩展为Object但不会为Long
  6.   
  7. 加宽节拍拳击,拳击比赛。
  8.   
  9. 你可以选择Box然后加宽(一个int可以通过整数成为对象)
  10.   
  11. 你不能加宽然后Box(一个int不能变长)
  12.   
  13. 你不能将var-args与两个加宽拳击结合起来。
  14.   

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

因此,考虑到这些规则,我们可以了解这里发生了什么:

根据规则一,原始扩展使用尽可能最具体的方法参数。由于int由非十进制数表示(例如1),而double由十进制数表示,精度比{{1}高32个字节(例如float),我们可以说1.0 s是“小于”或“小于”int s,按照这种逻辑,double可以是“晋升”为intdouble可以“降级”为double

简单地说,可以扩展到另一个原语的原语(例如int - > int - > float更具体另一个。例如,double 更具体而不是int,因为double可以提升为1

当你没有传递这些重载的同名vararg方法的参数时,由于返回实际上是相同的(分别为0和0.0),编译器会选择使用类型为{{vararg>的vararg的方法。 1}}因为更具体

那么,当你介绍分别引入1.0int s(不能相互扩展的类型)的相同方法时,编译器现在无法选择使用的方法因为int s不能像boolean s,intint那样被“提升”或“降级”。因此,它会抛出编译错误。

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