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

Java:重载方法解析和varargs——令人困惑的示例,java,variadic-functions,jls,Java,Variadic Functions,Jls,就在我认为我理解它适用于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) { ret

就在我认为我理解它适用于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
我理解第一行:说方法解析分阶段进行,第1阶段和第2阶段忽略varargs方法以确定是否有兼容的方法,第3阶段(包括varargs)仅在第1阶段和第2阶段失败时进行。(参见JLS和)因此,如果
compute(对象obj1,对象obj2)
适用,则
compute(字符串s,对象…对象)
总是被忽略

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


编辑:

…还有这个

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

prints
42

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

参考:

第节:

如果最后一个形式参数是
T
类型的变量arity参数, 可以考虑定义类型为
T[]
的形式参数


因为您显式地提供了一个数组,这允许第二个调用在第一阶段匹配variable arity方法,而不考虑variable arity。

我认为var args是在数组中转换的。所以,对我来说,第二行是合乎逻辑的。我的意思是,一个对象[]应该先匹配一个对象[],然后再匹配一个对象。@Jason:我同意,但我不是问什么是逻辑的,我是问JLS规定了什么。我正在研究反射运行时方法调度,以使其尽可能与编译时方法调度兼容,为了做到这一点,我需要遵循一个明确的标准,而不仅仅是我认为正确的观察行为。所有这些的“逻辑”结果是打印42,因为“hi”是
字符串
,因此比
对象
更匹配。因此,“更好”有两个相互冲突的衡量标准,因此你必须依赖JLS给出的规范性定义。啊!(灯泡出现)好的,所以变量算术方法也可以被认为是适用于兼容数组参数的固定算术方法。它是8.4.1--如果你编辑链接到我会接受。这就是我阅读它的方式。然后在15.12.2.5中,compute(Object,Object[])方法比compute(Object,Object)方法更具体。