Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is List<String> not a subtype of List<Object>? [duplicate]

Tags:

java

Possible Duplicate:
java generics covariance

I am trying to make sense of the fact that List<String> is not a subtype of List<Object>.

In effective Java, Josh Bloch notes that although it may seem counter-intuitive,it does make sense. The reason he stated is that you can put any Object in List<Object>, but can only put String in List<String>. I am not sure how this justifies why the String list is not a subtype of Object list.

Maybe I am confused by the term subtype. What I think it means is that when S is a subtype of T, an instance of S is an instance of T. Therefore, for List<String> to be a subtype of List<Object>, Object has to be a super class of String, which it technically is. Any idea where my reasoning went wrong?

like image 865
n_x_l Avatar asked Mar 07 '12 17:03

n_x_l


People also ask

Is List String a subtype of List object?

List<String> isn't type related to List<Object> in any way, not anymore than List<String> is related to List<Number> . The type is List<String> , the entire signature is the type . But like with everything, there are exceptions; these are called Wildcard Parameterized Types .

Is String a subtype of Object?

String is a subtype of Object , because the String class is a subclass of the Object class. int is not a subtype of Object , because none of Java's primitive types are subtypes of any reference type.

Is List integer a subtype of List object?

Although Integer is a subtype of Number, List<Integer> is not a subtype of List<Number> and, in fact, these two types are not related.

Is ArrayList a subtype of List?

So ArrayList<String> is a subtype of List<String>, which is a subtype of Collection<String>. So long as you do not vary the type argument, the subtyping relationship is preserved between the types.


2 Answers

List<String> s = new ArrayList<String>();
List<Object> o = s;
o.add(new Object());
String first = s.get(0);  // boom
like image 83
pholser Avatar answered Oct 05 '22 04:10

pholser


This goes back to what it means for A to be a subtype of B. The formal name for this is the Liskov substitution principle, which says basically that A is a subtype of B if and only if you can take any valid program that has in it something of type B, swap in something of type A and it would still be a valid program. The effect of this is that if you can use an A wherever you could use a B, then A is a subtype of B.

So in this case, since this is part of a valid (valid meaning "compiling") program:

public static void doThing(List<Object> x) {
  x.add(new Object());
}

Then, by the Liskov substitution principle, if List<String> were a subtype of List<Object> this would be part of a valid program too:

public static void doThing(List<String> y) {
  y.add(new Object());
}

But clearly that second snippet can't compile. Therefore, that second snippet is not part of a valid program, and therefore List<String> is not a subtype of List<Object>.

Likewise, the other way around is also not true: List<Object> is not a subtype of List<String>. Finding the program snippet to prove that is left as an exercise for the reader.

like image 26
Daniel Martin Avatar answered Oct 05 '22 04:10

Daniel Martin