Какой алгоритм выполняет определение типа T в статических методах только с <? супер T> <? расширяет T> args?
Collections
класс имеет статический метод copy
:
public static <T> void ...copy(List<? super T> dest, List<? extends T> src) {
//...
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
//...
}
Предполагается, что у меня есть иерархия:
- Apple.class -> Fruit.class (Apple является подтипом класса Fruit)
- Apple.class -> IMakeJuice.class (Apple является подтипом интерфейса IMakeJuice)
и я выполняю:
List<Object> objList = new ArrayList<Object>();
List<Apple> appleList = new ArrayList<Apple>();
Collections.copy(objList, appleList);
Будет ли T приведен к Fruit
, IMakeJuice
, Object
или же Apple
?
2 ответа
Это будет наиболее конкретный тип, который удовлетворяет границам, т.е. T
будет Apple
,
Цитирование https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html:
алгоритм вывода пытается найти наиболее конкретный тип, который работает со всеми аргументами.
Как уже ответил Энди Тернер, T
будет Apple
,
По другим подобным вопросам ваша IDE может рассказать вам. Я использую Eclipse, но я предполагаю, что другие тоже сделают это.
Если вы добавите следующее в любой файл.java:
class Test {
void test() {
List<Object> objList = new ArrayList<Object>();
List<Apple> appleList = new ArrayList<Apple>();
Collections.copy(objList, appleList);
}
}
class Fruit {}
interface IMakeJuice {}
class Apple extends Fruit implements IMakeJuice {}
Затем наведите курсор copy
или нажмите и нажмите клавишу F2, он покажет Javadoc с T
решено, включая определение метода:
<Apple> void java.util.Collections.copy(List<? super Apple> dest, List<? extends Apple> src)
Это также очень полезно для определения того, какой из многих перегруженных методов вызывается, например String.valueOf(1)
а также String.valueOf((short)1)
оба называют int
версия, пока String.valueOf(1.0)
позвонить double
версия.