繁体   English   中英

这个Java方法调用的歧义在哪里?

[英]Where is the ambiguity in this Java method call?

我得到一个“引用make is ambiguous”编译错误,我不明白。

我有这两种方法

public static <T> T make(String name, Class<T> parentClass, 
                         boolean rethrowRuntimeExceptions, 
                         Object... params) throws DLException

 public static <T> T make(String name, Class<T> parentClass,
                          Object... params) throws DLException

这行代码被标记为含糊不清

  String className = "clsNme";
  String one = "1";
  String two = "2";     
  SimpleFactory.make(className, Object.class, false, one, two);

这是错误

both method <T#1>make(String,Class<T#1>,boolean,Object...) in SimpleFactory and method <T#2>make(String,Class<T#2>,Object...) in SimpleFactory match
    [javac]   where T#1,T#2 are type-variables:
    [javac]     T#1 extends Object declared in method <T#1>make(String,Class<T#1>,boolean,Object...)
    [javac]     T#2 extends Object declared in method <T#2>make(String,Class<T#2>,Object...)

布尔参数的存在是否使第一个方法比第二个方法更接近?

如果重要,这是PowerMock测试的一部分。这是完整的方法

public void makeCallsMakeWithFalse() throws Throwable {
  Object expected = mock(Object.class);
  String className = "clsNme";

  String one = "1";
  String two = "2";

  spy(SimpleFactory.class);

  doReturn(expected).when(SimpleFactory.class);
  SimpleFactory.make(className, Object.class, false, one, two);  // causes error

  Object observed = SimpleFactory.make(className, Object.class, one, two); // doesn't cause error
  assertEquals(expected, observed);

  verifyStatic();
  SimpleFactory.make(className, Object.class, false, one, two);  // causes error

}

如果有帮助:我使用的是javac 1.8.0_77,Mokito 1.10.19和Powermock 1.6.3。

编译器首先尝试查找匹配的签名,但不涉及自动装箱/拆箱或变量arity调用 变量arity调用是指通过传递参数列表作为最后一个参数(而不是数组)来调用varargs方法。

在您的情况下,两者都涉及变量arity调用。 发生这种情况时,会选择最具体的过载。 对于您的情况,两者都不像JLS中定义的那样具体。 这主要是因为booleanObject类型都不是另一个的子类型。

稍微简化您的示例,以下内容无法编译。

static void foo(boolean b, Object... arr) {

}

static void foo(Object... arr) {

}

public static void main(String[] args) {
    foo(true);
}

第一个版本不接受Object类型的单个参数,第二个版本不接受boolean类型的单个参数。 因此,两者都不具体。 (Autoboxing只会使它看起来好像你可以传递boolean作为Object类型的参数)。

另一方面,如果用boolean替换boolean Boolean ,它会编译,因为BooleanObject的子类型。

问题在于

Object... params

当调用SimpleFactory.make(className, Object.class, false, one, two); Java不知道是否将“false”打包成一个布尔对象并将其作为“params”varargs数组的第一个参数传递(Boolean extends Object)并使用

make(String name, Class<T> parentClass, Object... params)

或者是否打电话

make(String name, Class<T> parentClass, boolean rethrowRuntimeExceptions, Object... params)

因为该签名也可以在params varargs之前接受布尔值。

因此,为什么它不明确,两种方法签名都适用。

我认为这是因为编译器不知道你是否希望boolean参数包含在params中。 我可以用4个参数调用函数并将boolean in作为第3个参数传递,或者它可以用3个参数调用函数并将boolean添加到Object ... params。 由于这种模糊性,编译器不知道该怎么做。 如果您需要更多信息,请与我们联系

问题在于

Object... params 

要修复歧义 - 更改下面的代码

打电话

public static <T> T make(String name, Class<T> parentClass, 
                         boolean rethrowRuntimeExceptions, 
                         Object... params) throws DLException

这样叫:

  SimpleFactory.make(className, Object.class, false, new Object[]{one, two});

打电话

 public static <T> T make(String name, Class<T> parentClass,
                          Object... params) throws DLException

这样叫:

  SimpleFactory.make(className, Object.class, new Object[]{false,one, two});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM