Java подстановочный знак нижней границы - PullRequest
0 голосов
/ 04 сентября 2018

Почему список в основном методе компилируется ниже?

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 ]

0 голосов
/ 04 сентября 2018

Компилятор Java использует определение типа для определения параметра типа для вызовов универсальных методов, таких как Arrays.asList. Он определяет наиболее конкретный тип, который может быть выведен как супертип для всех аргументов.

Для первого и второго списков в списке есть Object, поэтому Object является параметром предполагаемого типа. Это работает для ? super Drink, потому что ? super Drink является нижней границей, которой удовлетворяет Object. Это также работает для ?, неограниченного подстановочного знака, потому что ? будет соответствовать любому предполагаемому параметру типа. Они будут компилироваться, если у вас есть разные имена для этих двух переменных списка.

Для третьего списка (называемого fourthList?) У вас есть нижняя граница, ? extends Drink, означающая, что выведенный тип должен быть подтипом Drink, либо Drink, либо подклассом. Поскольку Breakfast является выводимым типом, а Breakfast не является подтипом Drink, это ошибка компилятора. Если бы Bread не было в списке, то выведенный тип был бы Drink, и это скомпилировалось бы.

0 голосов
/ 04 сентября 2018

extends является верхней границей - это означает, что любой указанный экземпляр не должен быть "выше" в иерархии наследования, чем указанный тип.

В вашем примере ? extends Drink - верхняя граница, поэтому каждый объект должен затем расширяться от Drink, чтобы быть юридически назначенным в этот список.

super является нижней границей - это означает, что любой указанный экземпляр не должен быть "более низким" в иерархии наследования, чем указанный тип.

Из вашего примера ? super Drink является нижней границей, поэтому каждый объект должен быть либо типом Drink, либо типом его предка - в данном случае Object.

? - это подстановочный знак - вы на самом деле не заботитесь , какой тип в коллекции, если вы его используете (поскольку вы не можете получить эту информацию обратно). По умолчанию это приводит к ? extends Object, и, следовательно, применяются правила верхней границы (и выполняются).

...