I'm using Java 8. During training to passing Java OCP 8 I find some snippets of code that I don't understand and want to know, why it so strange for me.
I have next hierarchy:
class A {}
class B extends A {}
class C extends B {}
The first one, this code is work:
List<?> list1 = new ArrayList<A>() {
{
add(new A());
}
};
But next code doesn't work, compilation error:
list1.add(new A());
So, why we can't add new record in this way?
The second one, this code is work:
List<? extends A> list2 = new ArrayList<A>() {
{
add(new A());
add(new B());
add(new C());
}
};
But next code doesn't work, compilation error:
list2.add(new A());
list2.add(new B());
list2.add(new C());
And the last one, this code is work:
List<? super B> list3 = new ArrayList<A>() {
{
add(new A());
add(new B());
add(new C());
}
};
But in the next code, when we adding new A(), compilation error:
list3.add(new A()); // compilation error
list3.add(new B());
list3.add(new C());
Thanks for your answers!
This is a compilation error designed to enforce type safety. If the compiler allowed you to do it, imagine what could happen:
For issue 1, once the object
list1has been declared, the compiler only considers the declared type, which isList<?>and ignores the fact that it was most recently assigned to anArrayList<A>.But:
Here, you are assigning to
list1an expression. The expression itself, i.e. everything after=, doesn't use?, and is in fact an anonymous class that extendsArrayList<A>and has an initializer block that callsadd(new A())which is ok.The second issue (with list2) has the same cause.
In the third issue,
The compiler sees
list3as aList<? super B>. This means the generic parameter can beBor its superclass,A. What if it's aList<B>? You can't add anAto aList<B>; therefore the compiler rejects this code.