I am trying to understand generics in Java and I have run into some problem. Here is the code I have written:
class Superclass{
}
class Subclass extends Superclass{
}
class Container <T>{
T elem;
}
public class Test {
public static void main(String[] args) {
Container<? extends Superclass> b = new Container<Superclass>();
b.elem = new Superclass();
}
}
This results i a strange exception that I just can't make sense of:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Type mismatch: cannot convert from Superclass to capture#1-of ?
at Test.main(Test.java:4)
I tried to make some changes. If i replace the commented line with:
Container<Superclass> b = new Container<Superclass>();
Everything works fine. That makes sense to me. It's just normal generics without any wildcard.
I then changed to commented line again:
Container<?> b = new Container<Superclass>();
I was surprised that this resulted in an exception too. However I found out that Java guarantees type safety even when using wildcards. I thing I understand why this results in an exception.
But I just can't make sense of why
Container<? extends Superclass> b = new Container<Superclass>();
results i an error. As far as I am aware, <? extends Superclass> means that I can use any subtype of Superclass in the container. And in Java Superclass is a Subtype of itself or at least functions like it were. I thought that by using extends Superclass there would be type safety and Java would accept the assignment.
I tried researching my problem but I wasn't able to find any satisfying answer. I would be very thankful if someone could help me out I tell me, were my mistake is and help me to understand why this line causes problems.
Suppose you had instead written
After the first line,
b.elemhas the "real type" ofSubclass. You can't assign aSuperclassto aSubclass, so the second line shouldn't have compiled.You have specifically told Java to forget the "real" type parameter of
b. It's known that it is some subclass ofSuperclass. But since it could beSubclass, and that wouldn't letb.elem = new Superclass()compile, it refuses to compile it.You can only use a
Container<? extends Superclass>in a way that would work no matter which subclass ofSuperclasswas actually used.b.elem = new Superclass()does not.This is normal and expected.