Java:重载方法解析和 varargs -- 令人困惑的示例

2022-09-04 21:29:25

就在我以为我理解了JLS15.12适用于varargs时,下面是这个例子:

package com.example.test.reflect;

public class MethodResolutionTest2 {
    public int compute(Object obj1, Object obj2) {
        return 42;
    }   
    public int compute(String s, Object... objects)
    {
        return 43;
    }

    public static void main(String[] args) {
        MethodResolutionTest2 mrt2 = new MethodResolutionTest2();
        System.out.println(mrt2.compute("hi",  mrt2));  
        System.out.println(mrt2.compute("hi",  new Object[]{mrt2}));    
        System.out.println(mrt2.compute("hi",  new Object[]{mrt2, mrt2, mrt2}));
    }
}

它打印出来

42
43
43

我理解第一行:JLS15.12表示方法解析发生在阶段,阶段1和2忽略varargs方法以找出是否存在兼容的方法,阶段3(包括varargs)仅在阶段1和2失败时才发生。(请参阅 JLS 和此 SO 问题。因此,如果适用,则始终会被忽略。compute(String s, Object... objects)compute(Object obj1, Object obj2)

但我不明白为什么另外两行印有43。An 也是 一个 的实例,那么为什么它与 varargs 方法匹配呢?Object[]Object


编辑:

...和这个

Object arg2 = new Object[]{mrt2};
System.out.println(mrt2.compute("hi", arg2));   

指纹。42


答案 1

在第 8.4.1 节中

如果最后一个形式参数是类型的变量 arity 参数,则认为它定义了类型的形式参数。TT[]

由于您显式提供了一个数组,因此这允许后两个调用在第一阶段中匹配变量 arity 方法,而不考虑变量 arity。


答案 2

Vararg 方法可以使用多个参数 (a, b, c) 或数组 ({a, b, c}) 调用。因为您正在传递一个与 varargs 类型匹配的数组,所以它优先。

参考资料: http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.1