Thursday, January 7, 2016

Caveat - JVM cannot check a generic cast at runtime

The Java Generics is based on Erasure, which means the type check is only done at compile time, and at runtime the type information is erased.

The following code will throw an ClassCastExceptionbecause there is no way the JVM can check the cast at runtime.

 public static void main(String[] args) {
  List<String> strings = createList(1);
  String string = strings.get(0); //ClassCastException here
  System.out.println(string);
 }
 
 public static <E> List<E> createList(Object object) {
  List<E> list = new ArrayList<>();
  E element = (E)object;
  list.add(element);
  return list;
 }

At runtime, the list object's type is just List. When using type parameter E to cast the object, the element's type is just Object and it's legal to add an Object to List. But when trying to get an element from the strings, the cast (generated by compiler) throws an ClassCastException as an Integer cannot be casted into a String.