Reputation:
I try to understand how is it possible to have a Double
value into an ArrayList
of Integer
. The numList
is an ArrayList
of Integer
, and the value from it is a Double
.
This is the code:
package bounded.wildcards;
import java.util.ArrayList;
import java.util.List;
public class GenericsDemo {
public static void main(String[] args) {
// Invariance Workaround
List<Integer> numList = new ArrayList<>();
GenericsDemo.invarianceWorkaround(numList);
System.out.println(numList);
}
static <T extends Number> void invarianceWorkaround(List<T> list) {
T element = (T) new Double(23.3);
list.add(element);
}
}
This will compile and run without an error.
Upvotes: 15
Views: 3078
Reputation: 12440
This is because of type erasure used with Java generics - the type checks are only performed at compile time for generic types, and the type info for generics is then erased, effectively turning List<Integer>
into List<Object>
.
My IDE warns you of an "Unchecked cast from Double to T". But the compiler couldn't be sure that your code is wrong, so it does not emit an error, just a warning.
Then at runtime, the type check is no longer present due to type erasure, so the code will run without error unless you perform some operation that fails due to incompatible runtime type. System.out.println()
is not such operation.
If you change the print code to
Integer num = numList.get(0);
System.out.println(num);
this will now involve runtime type check and will therefore fail:
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
Upvotes: 21