2015-02-19 7 views
1

, пожалуйста, помогите мне понять, почему этот бросок снят:Неконтролируемых литых между подстановочным общим типом и общим типом

List<? extends String> t= ...; 
List<String> t2=(List<String>)t; 

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

Редактировать: Как указывалось, я должен был использовать не финальный класс. So:

List<? extends ConfigurationAdapter> t= new ArrayList<DATASOURCE_ConfigurationAdapter>(); 
List<ConfigurationAdapter> t2=(List<ConfigurationAdapter>)t; 

Это работает. Я не могу понять, почему он не установлен.

ответ

3

Я полагаю, пример может объяснить причину предупреждения.

Но давайте использовать другой тип, поскольку строки на самом деле не могут иметь подтипы в Java.

List<Integer> integers = new ArrayList<>(asList(1,2,3,4,5)); 
List<? extends Number> anyNumbers = integers; 

Теперь предположим, что мы заставляем актеров, что вы делаете, представьте, что вы даже могли бы сделать это без предупреждения

List<Number> numbers = (List<Number>) anyNumbers; 

Теперь вы можете сделать это:

numbers.add(3.5); 

И позже, в каком-то другом месте вашего кода, кто-то пытается использовать оригинальную коллекцию следующим образом:

for(Integer myInt: integers) { //ClassCastException 

} 

Вы получаете исключение ClassCastException, потому что теперь вы нарушили ожидания системы типов. Оригинальная коллекция должна принимать только целые числа, но вам удалось обмануть Java, чтобы заставить ее принимать любые числа, в данном случае двойные. Конечно, когда вы перебираете исходную коллекцию, ожидая целых чисел, когда вы найдете тот, который на самом деле не является целым числом, ваш код не будет работать.

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

+0

Спасибо! Пожалуйста, посмотрите на мой другой вопрос, я думаю, это связано ... Я чувствую, что вы можете помочь мне разобраться. http://stackoverflow.com/questions/28604179/class-assubclass-signature – CptWasp

+0

@CptWasp ОК, я просто попытался ответить на ваш другой вопрос, хотя я не думаю, что это точно связано. –

2

Для String это абсолютно безопасно, и вы можете игнорировать предупреждение. То же самое можно было бы использовать для любого типа, где тип - тип final class.

Для любого другого типа тип значения, присвоенного t, может быть List<SubtypeOfTheBound>. В этом случае он не может быть назначен List<Bound>.

Больше чтение:

+0

Спасибо; но этот код работает: 'List t = новый ArrayList (); Список t2 = (Список ) t; 'и DATASOURCE_ConfigurationAdapter - это подтип привязки ... Являясь четко определенным, приведение всегда работает ... или нет? – CptWasp

+0

@CptWasp Это работает, потому что вы его бросаете, сообщая компилятору, что знаете, что делаете. Он не удастся позже, когда вы добавите другой подтип 'DATASOURCE_ConfigurationAdapter' через' t' и попробуйте прочитать его как «ConfigurationAdapter» с 't2'. В этот момент вы получите «ClassCastException». –

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