Java:重载方法解析

5

我有以下重载方法:

private static void foo(short... a)
{
    System.out.println("Calling var-len");
}

private static void foo(int a, int b)
{
    System.out.println("Calling int-int");
}

private static void foo(int a, double b) //(3)
{
    System.out.println("Calling int-double");
}

private static void main (String[] args)
{
    foo((short)2, (short)5); //This one outputs "Calling int-int"
}

我知道可变元方法在方法解析阶段中具有最低优先级,因此在这种情况下,如果我调用foo((short)2, (short)4);,我会得到"Calling int-int"。
但是,如果我将方法(3)更改为foo(short a, double b),则会选择可变元方法!(Java 7)。有人能解释一下吗?

1
我自己运行了这段代码,但是出现了歧义错误,而没有执行第三个方法。请您可以发布一些测试吗? - cgf
使用Java 1.6 (OS X 10.6.8)时,我也可以得到varargs版本。我猜我也好奇为什么更改一个在任何情况下都不应该被选中的方法会影响哪个可行的方法被选中。看起来像是一个无关紧要的推论。 - Radiodef
@Radiodef 第三种方法(short,double)无法确定哪个是更具体的两个固定数量参数方法(int,int),因此应该是一个“模糊”的情况。我很惊讶Java选择了varargs。如果有适用的固定数量参数方法,则编译器不应查看可变数量参数方法(根据规范:http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.1)。 - One Two Three
@OneTwoThree 但是如果两者都不比另一个更具体,它难道不能合理地进入第三阶段吗?我一直在阅读规格说明,到目前为止我没有看到相关条款。 - Radiodef
好的,在第一阶段下面读一下注释:http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2 它说可变元方法在第一阶段被视为固定元方法。 - Radiodef
显示剩余4条评论
2个回答

2

对于 foo #2 具有类型 int, int 和 foo #3 具有类型 short, double,将两个 short 传递给方法,我猜结果是两种方法都不比另一种更具体。在这种情况下,正如文档所说,我猜可变数量的变量被评估为 short, short - Radiodef
@OneTwoThree 我也不认为这是一个令人满意的答案。如果是真的,那么基本上它只意味着可变元方法被评估为固定元数,但在第一阶段最后。但我没有看到规范中有任何其他迹象表明这是可能的行为。 - Radiodef
没错,这就是我想说的。规范中没有提到这种情况。我想知道这是否只是Java编译器上尚未报告的错误! - One Two Three
似乎很奇怪,我们根据Java版本得到不同的结果。我认为你和我都在使用Java 6,但我使用的是更新版本65。我不认为这应该有任何影响。 - Radiodef
我在使用RHE6、Java 1.6、更新24。我遇到了预期的模棱两可的编译时错误。我猜想它们在更新之间“加入”了这个bug! - One Two Three
显示剩余3条评论

-3

你的问题是Java中数字提升的典型例子。它试图解决精确签名匹配(short,short),但在你的情况下,你没有那个方法。Java检查后续兼容数据类型(比如int),将short和int数据类型提升,并尝试找到匹配项,最终找到了。

如果没有任何数字提升可用,则会在您的代码中解析为变量参数方法。

请阅读以下链接上的数字提升内容。 http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html


如果它促进了args,那么应该选择接受int, int的方法吗? - 0x56794E
2
我相信 OP 知道短语正在被推广。问题是为什么将第三个方法从 int, double 更改为 short, double 会导致选择 varargs 方法而不是 int 方法。问题是为什么更改一个被认为永远不会被调用的方法会改变哪个方法被调用。这似乎是不合逻辑的。 - Radiodef

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接