Why does a type conversion not work in Java [duplicate]

余生颓废 提交于 2019-12-13 15:41:28

问题


I`m wondering why this conversion is not working:

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

I may have to add that Song extends MediaItem. I think this conversion should work because Song has the ability to store all the information form MediaItem. So no information is lost. Does anyone have an explanation for me?


回答1:


This is because generic types in Java have no covariance/contravariance. If you could do the assignment like that, one would be able to do this:

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 does not want this to happen. Hence, it prohibits assignments of generic types based on subclasses to generic types based on the corresponding base classes.




回答2:


Does anyone have an explanation for me?

If that assignment were valid, then you could put an instance of another subclass of Song (completely unrelated to MediaItem) into the list. Hence it's not allowed. In other words, Java generics are not covariant.




回答3:


This won't work because generics in Java not covariant. Meaning, List<Song> and List<MediaType> are two totally unrelated types, even though Song and MediaType are related.




回答4:


Your ArrayLists have different concrete parameterized type .

Read more about this in GenericTypes.FAQ101

An instantiation of a generic type where all type arguments are concrete types rather than wildcards. Examples of concrete parameterized types are List<String>, Map<String,Date>, but not List<? extends Number> or Map<String,?>.

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

Generic collections are not covariant. An instantiation of a parameterized type for a supertype is not considered a supertype of an instantiation of the same parameterized type for a subtype. That is, a LinkedList<Object> is not a supertype of LinkedList<String> and consequently a LinkedList<String> cannot be used where a LinkedList<Object> is expected; there is no assignment compatibility between those two instantiations of the same parameterized type, etc.

Here is an example that illustrates the difference:

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

You can achieve this by erasing parametrized type and casting:

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



回答5:


It's contradictory. On one hand, an ArrayList of Songs is declared, so Songs and objects of classes derived from Song can be stored there. However, new ArrayList<MediaItem>() is creating an ArrayList of the derived type, meaning that other objects derived directly from Song can't be stored. The difference between the types is irreconcilable.



来源:https://stackoverflow.com/questions/20940652/why-does-a-type-conversion-not-work-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!