Question

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?

Was it helpful?

Solution 2

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.

OTHER TIPS

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.

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.

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>();

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top