可变参数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使用哪种重载方法时,遵循了一些规则。
去引用:
- 原始扩展使用可能的最小方法参数
- 包装types不能扩展到另一个包装types
- 你可以从int到Integer,然后加宽到Object而不是Long
- 加宽的拳击拳击,拳击节奏Var-args。
- 你可以Box然后扩展(int可以通过Integer变成Object)
- 你不能扩大,然后框(一个int不能变长)
- 你不能把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
)的原语比另一个更具体 。 例如, int
比double
更具体 ,因为1
可以提升为1.0
。
当你没有参数传入这些相同名字的重载可变参数方法时,由于返回值实际上是相同的(分别为0和0.0),所以编译器会select使用types为int
的可变参数的方法,因为它更多具体 。
那么,当你引入这些相同的方法,分别取int
和s(不能相互扩展的types)时,编译器现在不能select一个方法来使用,因为int
s不能被“升级”或“降级“像int
s, float
s和double
s。 因此,它会抛出一个编译错误。
我希望这可以帮助你理解发生的事情。