pst*_*ton 21 java overloading variadic-functions
Java varargs实现中似乎存在一个错误.当方法使用不同类型的vararg参数重载时,Java无法区分适当的类型.
它给了我一个错误 The method ... is ambiguous for the type ...
请考虑以下代码:
public class Test
{
public static void main(String[] args) throws Throwable
{
doit(new int[]{1, 2}); // <- no problem
doit(new double[]{1.2, 2.2}); // <- no problem
doit(1.2f, 2.2f); // <- no problem
doit(1.2d, 2.2d); // <- no problem
doit(1, 2); // <- The method doit(double[]) is ambiguous for the type Test
}
public static void doit(double... ds)
{
System.out.println("doubles");
}
public static void doit(int... is)
{
System.out.println("ints");
}
}
Run Code Online (Sandbox Code Playgroud)
该文件说:"一般来说,你不应该重载可变参数的方法,或将难以程序员找出哪些超载被调用."
但是他们并没有提到这个错误,并不是程序员发现它很困难,而是编译器.
想法?
编辑 - 编译器:Sun jdk 1.6.0 u18
Ste*_*n C 13
问题是,它是不明确的.
doIt(1, 2);
Run Code Online (Sandbox Code Playgroud)
可能是一个电话doIt(int ...),或doIt(double ...).在后一种情况下,整数文字将被提升为double值.
我很确定Java规范说这是一个模糊的构造,编译器只是遵循规范规定的规则.(我必须进一步研究这个以确定.)
编辑 - JLS的相关部分是" 15.12.2.5选择最具体的方法 ",但这让我头疼.
我认为推理将void doIt(int[])不是更具体(反之亦然),而不是void doIt(double[])因为int[]它不是子类型double[](反之亦然).由于两个重载具有相同的特定性,因此调用是模糊的.
与此相反,void doItAgain(int) 是更具体的比void doItAgain(double)因为int是的子类型double根据所述JLS.因此,呼叫doItAgain(42)不是模棱两可的.
编辑2 - @finnw是对的,这是一个错误.考虑15.12.2.5的这一部分(编辑以删除不适用的案例):
一个名为m的变量arity成员方法比另一个同名的变量arity成员方法更具体,如果:
一个成员方法有n个参数,另一个成员方法有k个参数,其中n≥k.第一个成员方法的参数类型是T1 ,. ..,Tn-1,Tn [],其他方法的参数类型是U1 ,. ..,Uk-1,英国[].设Si = Ui,1 <= i <= k.然后:
- 对于从1到k-1的所有j,Tj <:Sj,和,
- 对于从k到n的所有j,Tj <:Sk
将此应用于n = k = 1的情况,我们看到它doIt(int[])更具体doIt(double[]).
事实上,有一个bug报告本和Sun承认,这的确是一个错误,虽然他们已经优先为"非常低".该错误现在在Java 7(b123)中标记为已修复.