2010-04-18 4 views
19

У меня возникли проблемы с пониманием к следующей статье: http://www.ibm.com/developerworks/java/library/j-jtp01255.htmlJava дженериков ковариационной

Under,

Дженерики не КОВАРИАНТНОЙ

автор заявляет,,

Поскольку ln - это список, добавив Поплавок к нему кажется совершенно законным. Но если пер были совмещенные с ли, то разорвет типа безопасности обещания неявного в определении Li - , что это список целых чисел, которые поэтому общие типы не могут быть ковариантны.

Я не могу понять, в каком месте он говорит «Если бы вы были с aliased ли». Что означает автор по псевдониму? (Ссылка?). Фрагмент кода выше цитируемой строки, кажется, иллюстрирует ЧТО является незаконным в Java, а не ПОЧЕМУ. Было бы очень полезно, если бы кто-нибудь мог объяснить пример. Спасибо заранее.

+0

IIRC, общие типы не ковариантны, потому что они не могли изменить, как массивы были реализованы/использованные в предыдущих версиях Java (обратная совместимость), она звонит колокол кому-то? – Rhangaun

+0

@Skeptic, Массивы - пример того, как может выглядеть реализация ковариантных дженериков - это приведет к выбросам исключений во время выполнения. Java не может этого сделать, потому что дженерики стираются во время выполнения, поэтому он может управлять только через ограничение ковариации. – Yishai

+0

@ Yishai, эта проблема с массивами обсуждалась Стилом в презентации под названием «Рост языка», которую я, похоже, сейчас не могу найти. – Rhangaun

ответ

39
List<Integer> li = new ArrayList<Integer>(); 
List<Number> ln = li; // illegal 
ln.add(new Float(3.1415)); 

В Java, Integer наследует от числа (java.lang.Number), поэтому интуитивно, все, что является Integer (java.lang.Integer) также число, но то, что статья указывает на то, что с дженериков не работает таким образом, потому что, учитывая, что Например, вы можете положить float (который является Number) в List<Integer>, что является незаконным, поскольку float не является целым числом.

Вывод: Дженерики не ковариантны.

Примечание: Я рекомендую вам прочитать Эффективная Java (2-е издание) Глава 5: Общие.

+0

Спасибо. 8) Я думал, что объяснение не имеет ничего общего с фрагментом кода. Дурак я. – soocracy42

+0

+1 для reco для чтения Эффективная Java. Я писал код в течение многих лет, и взял EJ месяц назад и сразу узнал 5 или 6 чрезвычайно важных стратегий. –

+0

Эта статья также очень полезна: https://www.ibm.com/developerworks/java/library/j-jtp01255/index.html –

8

Если бы вы могли сделать что-то вроде этого:

List<Float> foo; 
List<Object> bar; 

foo = new ArrayList<Float>(); 
bar = foo; 

foo.add(1.0f); 
bar.add("Hello"); 

все пойдет очень неправильно. В этом примере панель является псевдонимом для foo, и если вы можете это сделать, вы потеряете безопасность типа, которая является основной причиной существования дженериков.

+0

Большое спасибо. Я не был уверен в части псевдонима. Это подтверждает мое предположение. – soocracy42

+0

Ах! Итак, теперь «Привет» не только в 'bar' (что, вероятно, будет хорошо), но и в' foo'. Наконец, это имеет смысл :) Думаю, тогда я мог бы объявить метод листинга списка, который должен был бы скопировать список, hm. –

-2
public class vechicle { 
void drive(){ 
} 
} 
class car extends vechicle{ 
     //Covariance 
    vechicle getObject(){ 
     return new car(); 
    } 
     //contravariance 
    car getmyObject(){ 
     return (car) new vechicle(); 
    } 
} 
+0

java.lang.ClassCastException будет повышаться в 'return (car) new vechicle();' – Rembo

Смежные вопросы