Ответ 1
Это, в основном, компилятор, решающий вызывать наиболее специфический метод среди всех.
Когда вы вызываете
System.out.println(foo(i));//Object[]... vs Integer[]...
он выберет foo(Integer[]... args)
Потому что во время выполнения JVM делегирует вызов методу с аргументом Integer[][]
и not method с Object[][]
param, как указано varags. Поскольку более конкретным будет метод вызова с Integer [] [], а не Object [] [].
В более позднем заявлении, когда вы вызываете
System.out.println(bar(i));//Object... vs Integer[]...
он перейдет к bar(Object... args)
Снова с помощью varags тип param будет Object [], а не Object [] []. Опять же, компилятор вызовет наиболее специфический метод, который будет иметь Object... args
.
Если вы измените подпись метода, удалив varags следующим образом:
//Object... vs Integer[]...
public static String bar(Object args) {
return "Object args";
}
public static String bar(Integer[] args) {
return "Integer[] args";
}
то вы заметите, что он вызовет bar(Integer[] args)
, поскольку он более специфичен для вызова метода.
Точнее, чем JLS Subtyping среди типов массивов,
- Если S и T являются ссылочными типами, тогда S [] > T [], если S > T.
- Объект > Объект []
Это означает, что вызов Integer [] будет выполнен с использованием метода Integer [] [], а не Object [] []. Где в качестве вызова Integer [] будет сделан объект Object [], а не Integer [] [].
См. здесь для выбора наиболее конкретного метода.