kar*_*rim 68 java methods overloading variadic-functions
我对Java的varargs方法有点困惑:
public static int sum(int ...a) {
return 0;
}
public static double sum(double ...a) {
return 0.0;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试在sum()
不传递任何参数的情况下调用时,则int
调用了方法的版本.我不明白为什么; 通常编译器必须引发错误.
相反,当我尝试在sum
没有任何参数的情况下调用时,以下代码段会生成编译器错误:
public static int sum(int ...a) {
return 0;
}
public static boolean sum(boolean ...a) {
return true;
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*nik 56
这里适用的一般规则是:如果一个方法签名严格地比另一个更具体,那么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,参数ei比Ti更具体(1≤i≤n,n = k).
...
如果S <:T(§4.10),则类型S对于任何表达式比类型T更具体.
4.10.分型
4.10.1.原始类型之间的子类型
double> 1 float
漂浮> 1长
长> 1 int
如本回答所述,在选择要使用的重载方法时遵循规则.
报价:
- 原始扩展使用可能的最小方法参数
- 包装类型不能扩展到另一种包装类型
- 您可以从int到Integer并将其扩展为Object但不包含Long
- 加宽节拍拳击,拳击节拍Var-args.
- 你可以Box然后加宽(一个int可以通过整数成为对象)
- 你不能加宽然后Box(一个int不能变长)
- 不能合并VAR-ARGS,有两个加宽和拳击.
(让我们像这样重新定义规则1:"原始扩展使用尽可能最具体的方法参数.")
因此,考虑到这些规则,我们可以了解这里发生了什么:
根据规则一,原始扩展使用尽可能最具体的方法参数.由于a int
由非十进制数表示(例如1
),a double
由十进制数表示,精度比a float
(例如1.0
)的精度高32个字节,我们可以说int
s是"小于"或"小于" double
s,按照这种逻辑,int
s可以"升级"为double
s,double
s可以"降级"为int
s.
简而言之,可以扩展到另一个原语(例如int
- > float
- > double
)的原语比另一个原语更具体.例如,一个int
是更具体的比double
,因为1
可以提升1.0
.
当你没有传递这些重载的同名vararg方法的参数时,由于返回实际上是相同的(分别为0和0.0),编译器会选择使用接受vararg类型的方法,int
因为它更具体.
那么,当你介绍分别采用int
s和boolean
s(相互之间不能加宽的类型)的相同方法时,编译器现在无法选择使用的方法,因为int
s不能像int
s 那样被"提升"或"降级" ,float
s和double
s.因此,它会抛出编译错误.
我希望这可以帮助您了解正在发生的事情.
归档时间: |
|
查看次数: |
1654 次 |
最近记录: |