2014-01-05 2 views
2

I`m интересно, почему это преобразование не работает:Почему преобразование типов не работает в Java

ArrayList<Song> arrayList =new ArrayList<MediaItem>(); 

Я, возможно, придется добавить, что песня расширяет MediaItem. Я думаю, что это преобразование должно работать, потому что Song имеет возможность хранить всю информационную форму MediaItem. Таким образом, информация не теряется. У кого-нибудь есть объяснение для меня?

+0

http://stackoverflow.com/questions/933447/how-do-you-cast-a-list-of-objects-from-one-type-to-another-in-java/933600 # 933600 – MariuszS

+0

Какое преобразование? Вы просто назначаете ссылку на один тип объекта на другой тип объекта. Даже если бы это было разрешено, ничто не было бы «преобразовано». –

+0

Мой ответ [здесь] (http://stackoverflow.com/a/20042341/1081110) на соответствующий вопрос объясняет это. –

ответ

2

Это связано с тем, что общие типы Java не имеют ковариации/контравариантности. Если бы вы могли выполнить задание, как это, можно было бы быть в состоянии сделать это:

ArrayList<MediaItem> mediaItems = new ArrayList<MediaItem>(); // Legal 
ArrayList<Song> songs = mediaItems; // Illegal; let's imagine it's legal for a moment 
// Note that songs and mediaItems are the same list 
songs.add(new Song());   // This is perfectly fine 
Song firstSong = songs.get(0); // That's OK - it's a Song 
mediaItems.add(new Video()); // This is perfectly fine, too 
// However, the addition above also modifies songs: remember, it's the same list. 
// Now let's get the last object from songs 
Song lastSong = songs.get(1); // Wait, that's not a Song, it's a Video!!! 

Java не хочет, чтобы это произошло. Следовательно, он запрещает присвоения родовых типов на основе подклассов общим типам на основе соответствующих базовых классов.

+1

Вы уверены, что ваша первая линия является законной? Должен не быть MediaItem с обеих сторон –

+0

@RichardTingle Абсолютно, вы на 100% правы! Это была ошибка копирования-вставки. Когда вы видите тупую ошибку, подобную этой, отредактируйте, пожалуйста, свободно. Большое спасибо! – dasblinkenlight

4

У кого-нибудь есть объяснение для меня?

Если это назначение было справедливо, то вы могли бы поместить экземпляр другого подкласса Song (совершенно не связаны с MediaItem) в список. Следовательно, это запрещено. Другими словами, Java-дженерики не являются covariant.

2

Это не сработает, потому что дженерики Java не ковариантны. Значение, List<Song> и List<MediaType> - два совершенно несвязанных типа, хотя Song и MediaType связаны между собой.

0

Это противоречиво. С одной стороны, объявляется ArrayList Song s, поэтому Song s и объекты классов, полученные из Song, могут быть сохранены там. Однако new ArrayList<MediaItem>() создает ArrayList производного типа, что означает, что другие объекты, полученные непосредственно из Song, не могут быть сохранены в. Разница между типами непримирима.

2

Ваш ArrayList s имеет различный конкретный параметризованный тип.

Подробнее об этом в GenericTypes.FAQ101

конкретизации общего типа, где все аргументы типа являются конкретными типами, а не групповые символами. Примеры конкретных параметризованных типов: List<String>, Map<String,Date>, но не List<? extends Number> или Map<String,?>.

Arrays in Java Generics - What are the issues regarding arrays in Java Generics?

Generic коллекция не ковариантна. Инстанцирование параметризованного типа для супертипа не считается супертипом экземпляра того же параметризованного типа для подтипа. То есть LinkedList<Object> не является супертипом LinkedList<String>, и поэтому LinkedList<String> не может использоваться там, где ожидается LinkedList<Object>; нет совместимости присвоений между этими двумя экземплярами того же параметризованного типа и т. д.

Вот пример, который иллюстрирует разницу:

LinkedList<Object> objLst = new LinkedList<String>(); // compile-time error

Вы можете достичь этого путем стирания параметризованную типа и литье:

ArrayList<Song> arrayList = (ArrayList<Song>) (ArrayList<?>) new ArrayList<MediaItem>(); 
Смежные вопросы