Spec-Zone .ru
спецификации, руководства, описания, API
|
Давайте протестируем Ваше понимание обобщений. Действительно ли следующий фрагмент кода является законным?
List<String> ls = new ArrayList<String>(); // 1 List<Object> lo = ls; // 2
Строка 1 является, конечно, законной. Более хитрая часть вопроса является строкой 2. Это сводится к вопросу: a List
из String
a List
из Object
. Большинство людей инстинктивно отвечает, "Уверенный!"
Ну, смотрите на следующие немного строк:
lo.add(new Object()); // 3 String s = ls.get(0); // 4: Attempts to assign an Object to a String!
Здесь мы исказили ls
и lo
. Доступ ls
, список String
, через псевдоним lo
, мы можем вставить произвольные объекты в это. В результате ls
не содержит только String
s больше, и когда мы пытаемся вытащить что-то из этого, мы получаем грубое удивление.
Компилятор Java предотвратит это, конечно. Строка 2 вызовет ошибку времени компиляции.
Вообще, если Foo
подтип (подкласс или подынтерфейс) Bar
, и G
некоторое универсальное описание типа, не то, что G<Foo>
подтип G<Bar>
. Это - вероятно, самая твердая вещь, Вы должны узнать об обобщениях, потому что она идет вразрез с нашими глубоко сохраненными интуициями.
Мы не должны предположить, что наборы не изменяются. Наш инстинкт может привести нас думать об этих вещах как неизменных.
Например, если отдел автомашин предоставляет список драйверов в бюро переписи, это кажется разумным. Мы думаем это a List<Driver>
a List<Person>
, принятие этого Driver
подтип Person
. Фактически, что передают, копия реестра драйверов. Иначе, бюро переписи могло добавить новых людей, которые не являются драйверами в список, повреждая записи DMV.
Чтобы справиться с этим видом ситуации, полезно рассмотреть более гибкие универсальные типы. Правила, которые мы видели до сих пор, являются довольно рестриктивными.