2015-02-15 2 views
1

Я знаю Дженерики инвариантны: для любых двух различных типов Type1 и TYPE2, Список < Type1> не является ни подтипом, ни супертипом Список < Type2>Wildcards в Java дженериков

так

List<someObject> nums = new ArrayList<someObject>(); // this is correct 
List<Object> nums = new ArrayList<subObject>(); // this is not correct 

но

List<Number> nums = new ArrayList<Number>(); 
List<? super Number> sink = nums; ????(line 2) 

пусть говорят, что если подстановочные это объект так строка 2 Виль

List<Object> sink = List<Number> nums 

кажется, что инвариантное правило не применяется здесь

может кто-нибудь объяснить мне, почему линия 2 компилируется без ошибок?

Спасибо так много

+3

Я не уверен, что понимаю, о чем вы спрашиваете. Третья строка кода, которая у вас есть, является недопустимым синтаксисом. – Makoto

+2

Взгляните на [PECS] (http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs). –

+0

Не могу сказать, что вы пытаетесь спросить. * "скажем, если wildcard является Object, поэтому строка 2 wil be" * 'List sink = Список nums' Это не имеет никакого смысла. – Radiodef

ответ

2

Если я не ошибаюсь, вы хотите иметь объяснение о том, как это ниже правильный код:

List<Number> nums = new ArrayList<Number>(); 
List<? super Number> sink = nums; 

Инвариантность является свойством класса о том, как его параметр типа влияет на его подтипов.

Дженерики являются инвариантными, но существуют дикие карты, которые помогают нам с подтипами. Они не очень полезны, поскольку они не представляют никакого типа, но представляют собой хороший взлом.Ниже действует

List<Animal> <: List<?> 
List<?>  <: List 

Лучше пример:

List<? super Animal> d1= new ArrayList<Animal>(); 
d1.add(new Animal()); 
d1.add(new Dog()); 

Вышеуказанные работы, потому что d1 имеет тип List<? super Animal>. Вы можете представить себе add функцию вести себя, как:

boolean add(? super Animal e); 

Так add метод можно передать любую переменную, которая подтип из ? super Animal. И

Animal <: ? super Animal 
Dog <: ? super Animal 

Так что добавление собаки или животных работает. Таким образом, d1 действует как список, который может принимать любой параметр типа Animal или подтип, если он.

Аналогичным образом, вы также можете иметь ниже. Но технически вы не можете ничего добавить в этот список. Если в java существовал sometype, который является подтипом каждого типа, тогда вы можете правильно добавить к нему элемент этого типа. Ничего больше.

ArrayList<? extends Animal> d1 = new ArrayList<Animal>(); 

Посмотрите на этот ответ для получения более info.

-1

Позволяет иметь:

List<Integer> li = new ArrayList<>(); 
List<Object> lo = new ArrayList<>(); 
l = lo;//not allowed 
lo.add("string"); 
Integer i = li.get(0);//that is string there 

Вот почему вы не можете сделать такое назначение. Я думаю, что компилятор не рассматривает прямое назначение new ArrayList<Integer>() другой существующей переменной li.

+0

Это не тот вопрос, который задают – Jatin

1

Действительно, правило инварианта применяется. Примечание:

List<? super Number> sink = nums; 

просто не работает, как вы думаете.

Ожидает, что вы считаете, что объект типа ArrayList можно присвоить переменной типа List<? super Number>, поскольку первый является подклассом последнего. Это нарушит правило инварианта, но это не то, что происходит.

Переменная List<? super Number> представляет собой набор всех возможных списков, где someClass является числом или является предком номера.

пусть говорит, что если подстановочное это объект так строка 2 Виль

 `List<Object> sink = List<Number> nums ` 

В этом контексте? не устанавливается произвольно, поэтому этого не происходит.

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