我得到一个"引用make是模棱两可的"编译错误,我不明白。
我有这两种方法
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。
答案 0 :(得分:6)
编译器首先尝试查找匹配的签名,但不涉及自动装箱/拆箱或变量arity调用。变量arity调用是指通过传递参数列表作为最后一个参数(而不是数组)来调用varargs方法。
在您的情况下,两者都涉及变量arity调用。发生这种情况时,会选择最具体的过载。对于您的情况,两者都不像JLS中定义的那样具体。这主要是因为boolean
和Object
类型都不是另一种类型的子类型。
稍微简化您的示例,以下内容无法编译。
static void foo(boolean b, Object... arr) {
}
static void foo(Object... arr) {
}
public static void main(String[] args) {
foo(true);
}
第一个版本不接受Object
类型的单个参数,第二个版本不接受类型为boolean
的单个参数。因此,两者都不具体。 (自动装箱只会让它看起来就像你可以将boolean
作为Object
类型的参数传递一样。)
另一方面,如果您将boolean
替换为Boolean
,则会进行编译,因为Boolean
是Object
的子类型。
答案 1 :(得分:5)
问题在于
Object... params
致电SimpleFactory.make(className, Object.class, false, one, two);
时
Java不会知道是否打包&#34; false&#34;进入一个布尔对象并将其作为&#34; params&#34;的第一个参数传递给它。 varargs array(Boolean extends Object)并使用
make(String name, Class<T> parentClass, Object... params)
或是否致电
make(String name, Class<T> parentClass, boolean rethrowRuntimeExceptions, Object... params)
因为该签名也可以在params varargs之前接受布尔值。
因此,为什么它不明确,两种方法签名都适用。
答案 2 :(得分:1)
我认为这是因为编译器不知道你是否想要将boolean参数包含在params中。我可以用4个参数调用函数并将boolean in作为第3个参数传递,或者它可以用3个参数调用函数并将boolean添加到Object ... params。由于这种模糊性,编译器不知道该怎么做。如果您需要更多信息,请告诉我
答案 3 :(得分:1)
问题在于
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});