当前位置: 首页 > 面试题库 >

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

孟鸿朗
2023-03-14
问题内容

就在我以为我了解适用于varargs的JLS15.12时,这是这个示例:

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方法来确定是否存在兼容的方法,只有阶段1和2失败时才发生阶段3(包括varargs)。(请参阅JLS和此SO问题。)因此,compute(String s, Object... objects)如果compute(Object obj1, Object obj2)适用,将始终被忽略。

但是我不明白为什么其他两行打印43。An Object[]也是的实例Object,那么为什么它与varargs方法匹配?

编辑:

…还有这个

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

版画42


问题答案:

在8.4.1节中:

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

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



 类似资料:
  • 我希望类中的方法在IO线程上运行一些代码,但只有一次它们订阅的主题具有特定值。然后调用者应该在AndroidUI线程上得到响应。 像这样的东西: 这有用吗?不确定,所以我写了一组单元测试来检查它们。我发现我的测试方法,尽管它们在一个接一个地运行时总是有效的,但作为套件的一部分会失败。 事实上,我发现如果我把同样的测试进行两次,第一次会通过,但第二次会失败! 为什么会这样?被测类中的bug是,还是测

  • 本文向大家介绍Java Varargs中的方法重载和歧义,包括了Java Varargs中的方法重载和歧义的使用技巧和注意事项,需要的朋友参考一下 在Java中使用变量参数时存在歧义。发生这种情况是因为两种方法绝对可以有效地被数据值调用。因此,编译器不知道该调用哪种方法。 示例 输出结果 名为Demo的类定义了一个名为“ my_fun”的函数,该函数采用可变数量的浮点值。使用“ for”循环将这些

  • 这是一个练习2D数组的练习,显然我在理解它们方面失败了。输入是创建一个方法,该方法在数组[][]中查找最大的沙漏形整数数。数组的大小总是6x6,因此循环是x<4和y<4,整数值也是从-9到9,这就是为什么我的结果变量以-256开始(如果我以0开始,充满负值的数组将不起作用) 样本输入 即产生输出的沙漏形状 然后在main中使用我的biggestHourglass()方法。 我的结果不符合预期,我不

  • 问题内容: 以下代码无法编译。 发出编译时错误。 对test的引用是模棱两可的,varargspkg.Main中的方法test(int …)和varargspkg.Main中的方法test(float …) 这似乎很明显,因为方法调用中的参数值可以提升为 如果任何一个或两个参数都带有或作为后缀,则会进行编译。 但是,如果我们用相应的包装器类型表示方法签名中的接收参数,如下所示 那么对该方法的调用不

  • 问题内容: 有人可以向我解释一下吗: 我从不理解,我认真地认为,如果有人不尝试向我深入解释,我永远也不会。这整个上下文使我感到困惑。有时它是这样的: 有时它不会那样工作,但只接受: 有时是: 等等等等等。 我了解上下文的基础,但是有几项?为什么日食会一次又一次地向我抛出错误呢?为什么有时需要声明上下文?: 我无法在所有情况下都找到合适的环境,我怎么知道在每种情况下都合适的环境? 问题答案: 首先,

  • 问题内容: Javadoc说: 被调用的隐藏方法的版本是超类中的版本,被调用的重写方法的版本是子类中的版本。 不会向我敲钟。任何清楚的例子,表明其含义将不胜感激。 问题答案: 在这里,据说藏起来了。隐藏不像覆盖那样工作,因为静态方法不是多态的。因此,将发生以下情况: 在实例而不是类上调用静态方法是一种非常糟糕的做法,绝不应该这样做。 将其与实例方法进行比较,实例方法是多态的,因此被覆盖。调用的方法