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и, таким образом, применяются правила верхней границы (и они выполняются).

Другие вопросы по тегам