Где же двусмысленность в этом вызове метода Java?
Я получаю ошибку компилятора" ссылка для создания неоднозначна", которую я не понимаю.
У меня есть эти два метода
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.
4 ответа:
Проблема заключается в
Object... params
При вызове
SimpleFactory.make(className, Object.class, false, one, two);
Java не будет знать, Следует ли поместить "false" в логический объект и передать его в качестве первого аргумента массива varargs" params " (Boolean extends Object) и использоватьmake(String name, Class<T> parentClass, Object... params)
Или стоит ли звонить
make(String name, Class<T> parentClass, boolean rethrowRuntimeExceptions, Object... params)
Поскольку эта сигнатура также может принимать булево значение перед парами varargs.
Следовательно, почему это неоднозначно, применимы обе сигнатуры метода.
Компилятор сначала пытается найти соответствующую сигнатуру, которая не включает автобоксинг / распаковку иливызов переменной 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
.
Я думаю, это потому, что компилятор не знает, хотите ли вы, чтобы булев параметр был включен в params или нет. Я мог бы либо вызвать функцию с 4 параметрами и передать булеву в качестве 3-го параметра, либо она могла бы вызвать функцию с 3 параметрами и добавить булеву к объекту... параметры. Компилятор не знает, что делать из-за этой двусмысленности. Дайте мне знать, если вам нужна дополнительная информация
Проблема заключается в
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});