Java подстановочный знак нижней границы
Почему список в основном методе ниже компилируется?
class Breakfast {
}
class Drink extends Breakfast {
}
class Juice extends Drink {
}
class Food extends Breakfast {
}
class Bread extends Food {
}
public static void main(String[] args) {
Object object = new Object();
Drink drink = new Drink();
Juice juice = new Juice();
Bread bread = new Bread();
List<? super Drink> firstList = Arrays.asList(object, drink, juice, bread);
List<?> secondList = Arrays.asList(object, drink, juice, bread);
List<? extends Drink> thirdList = Arrays.asList(drink, juice, bread); //DOESN'T COMPILE
}
Видя, как хлеб не суперкласс Drink? Какое правило разрешает составление первого и второго списков, но не третьего? И если так, то каковы основные различия между
<?>
а также
<? super Drink>
Спасибо!
2 ответа
Компилятор Java использует определение типа для определения параметра типа для вызовов универсальных методов, таких как Arrays.asList
, Он определяет наиболее конкретный тип, который может быть выведен как супертип для всех аргументов.
Для первого и второго списков есть Object
в списке, так Object
является выводимым параметром типа. Это работает для ? super Drink
, так как ? super Drink
нижняя граница, которая Object
удовлетворяет. Это также работает для ?
, неограниченный шаблон, потому что ?
будет соответствовать любому предполагаемому параметру типа. Они будут компилироваться, если у вас есть разные имена для этих двух переменных списка.
Для третьего списка (называется fourthList
?), у вас есть нижняя граница, ? extends Drink
Это означает, что предполагаемый тип должен быть подтипом Drink
, или Drink
сам или подкласс. Так как Breakfast
является предполагаемым типом, и Breakfast
не является подтипом Drink
, это ошибка компилятора. Если Bread
не были бы в списке, то предполагаемый тип будет Drink
и это будет компилироваться.
extends
является верхней границей - это означает, что любой указанный экземпляр не должен быть "более высоким" в иерархии наследования, чем указанный тип.
Из вашего примера ? extends Drink
верхняя граница - поэтому каждый объект должен простираться от Drink
быть юридически назначен в этот список.
super
является нижней границей - это означает, что любой указанный экземпляр не должен быть "более низким" в иерархии наследования, чем указанный тип.
Из вашего примера ? super Drink
является нижней границей - поэтому каждый объект должен быть либо типом Drink
или тип его предка - в этом случае, Object
,
?
является подстановочным знаком - вам на самом деле все равно, какой тип в коллекции, если вы его используете (поскольку вы не можете получить эту информацию обратно). По умолчанию это приводит к ? extends Object
и, таким образом, применяются правила верхней границы (и они выполняются).