可变参数Java模糊呼叫

我对Java的可变参数方法有些困惑:

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

这里适用的一般规则是这样的:如果一个方法签名比另一个严格得多,那么Java会select它而不会出错。

直观地说,如果您可以完全删除方法签名,则方法签名更加具体,另一方面,不太具体的方法将适用于每个现有的调用。

当在签名sum(int... args)sum(double... args) ,签名sum(int... args)更具体,因为对该方法的任何调用也可以传递通过应用一个扩大的转换来sum(double... args) 。 同样不适用于sum(boolean... args)方法,它不能被类似地转换。

Java语言规范,SE 8版本:

15.12。 方法调用expression式

15.12.2.5。 select最具体的方法

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

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

  • m2不是通用的,m1和m2可以通过严格的或者宽松的调用来适用,其中m1具有forms参数typesS1,…,Sn,m2具有forms参数typesT1,…,Tn,typesSi 更多对于所有的i(1≤i≤n,n = k),对于自variablesei而言,都是比Ti更具体的

如果S <:T(§4.10),则typesS比任何expression式的typesT更具体。


4.10。 分型

4.10.1。 在原始types之间进行分类

双> 1浮动

浮动> 1长

长> 1整数

正如在这个答案中所提到的,在select使用哪种重载方法时,遵循了一些规则。

去引用:

  1. 原始扩展使用可能的最小方法参数
  2. 包装types不能扩展到另一个包装types
  3. 你可以从int到Integer,然后加宽到Object而不是Long
  4. 加宽的拳击拳击,拳击节奏Var-args。
  5. 你可以Box然后扩展(int可以通过Integer变成Object)
  6. 你不能扩大,然后框(一个int不能变长)
  7. 你不能把var-args与加宽装箱结合起来。

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

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

根据规则1,原始扩展尽可能使用最具体的方法参数。 由于一个int表示一个非十进制数(例如1 ),一个double表示一个十进制数,其精度比float多32个字节(例如1.0 ),所以可以说int s是“小于“或”小于“ double s,通过这个逻辑, int s可以被”提升“为double s, double s可以被”降级“为int s。

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

当你没有参数传入这些相同名字的重载可变参数方法时,由于返回值实际上是相同的(分别为0和0.0),所以编译器会select使用types为int的可变参数的方法,因为它更多具体

那么,当你引入这些相同的方法,分别取int和s(不能相互扩展的types)时,编译器现在不能select一个方法来使用,因为int s不能被“升级”或“降级“像int s, float s和double s。 因此,它会抛出一个编译错误。

我希望这可以帮助你理解发生的事情。

Interesting Posts