Monday, 30 July 2012

Java Generics I - Erasure, Benefits

Using Java Generics can be tricky. New developers often have a hard time grasping the nuts and bolts of this feature. These posts summarize the most common pitfalls and caveats.

How Are Generics Compiled in Java?

Technically speaking, generics are not compiled into bytecode in Java. They are preprocessed by the compiler, before the Java code itself is compiled into bytecode. This process is called type erasure.

This is best described with an example:
Queue<String> q = new PriorityQueue<String>();
String retr = q.element();

The above code in transformed into the following equivalent bytecode:
Queue q = new PriorityQueue();
String retr = (String) q.element();

The value returned by q.element() is cast into a String.

What is the Benefit of Generics?

The main benefit is to check at compile time that all elements inserted or retrieved from the q object are strings, because after compilation, any element could technically be inserted in it. This could trigger unexpected errors, such as ClassCastException at runtime.

If some external code imported the q object defined in the above generic Java code, the compiler would check that this external code uses q properly. In others words, it would check that it only inserts or retrieves strings from it.

Like this, one is sure that bytecode won't throw ClassCastException at runtime. It also means that the generic code does not need to be recompiled, only the external code needs compilation.

By not introducing generics at the bytecode level, Java code written and compiled before generics were available can still use Java code using generics. The future is safe for code of the past.

Part I  Part II   Part III   Part IV