Understanding Type Erasure In Java
In this article, Parag Shah looks at Type Erasure in Java, a process where the compiler removes all information related to type parameters and type arguments within a class or method.
—
Generics were first introduced in Java 1.5 . Even though everyone understands what Generics are and how to use them, the concept of type erasure is a bit illusive. In this article I will explain type erasure in generics, using a simple example.
Angelika Langer has an excellent FAQ, where she explains generics, and type erasure. Here is how she defines type erasure: A process that maps a parameterized type (or method) to its unique byte code representation by eliding type parameters and arguments.
OK, let’s understand what that means. Listing-1 shows a simple class which uses generics with Java Lists. In this example we create a list of Strings and iterate through the list.
[java]
package net.adaptivelearningonline.examples.generics;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GenericsErasure {
public static void main(String args[]) {
List<String> list = new ArrayList<String>();
list.add("Hello");
Iterator<String> iter = list.iterator();
while(iter.hasNext()) {
String s = iter.next();
System.out.println(s);
}
}
}
[/java]
Listing-1 : A simple class which uses Java generics
Now let’s do a little experiment to understand what type erasure means.
* Compile the above class
* Decompile GenericsErasure.class using JAD
The source generated from the decompilation is shown in Listing-2.
[java]
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: GenericsErasure.java
package net.adaptivelearningonline.examples.generics;
import java.io.PrintStream;
import java.util.*;
public class GenericsErasure
{
public GenericsErasure()
{
}
public static void main(String args[])
{
List list = new ArrayList();
list.add("Hello");
String s;
for(Iterator iter = list.iterator(); iter.hasNext(); System.out.println(s))
s = (String)iter.next();
}
}
[/java]
Listing-2 : Source of class (from Listing-1) decompiled by JAD
As you can see, the decompiled code has absolutely no trace of any generics related information when the List is declared. This is because of type erasure. Now let’s revisit Angelika’s definition of type erasure:
A process that maps a parameterized type (or method) to its unique byte code representation by eliding type parameters and arguments.
When the Java compiler compiles client code which uses a library that has been generified, the client code is compiled in such a way that all generics information (‘type parameters and arguments’ which is the in List) is erased from the bytecode. This also explains the fact that generics information in client code is meant purely for the compiler to do type checking. Once the compiler has done it’s job, this information is discarded.
If you are wondering why Java erases generics type information from compiled code – it is to maintain backwards compatibility. Let’s assume you wrote some code a few years back which used Java Lists, before generics was introduced in the language. Obviously your code did not use generics.
So back then you must have declared your List like this:
[java]
List list = new ArrayList();
[/java]
Listing-3
and not like this:
[java]
List<String> list = new ArrayList<String>();
[/java]
Listing-4
Now, when engineers at Sun decided to introduce generics, they did not want to break code which people had already written. Their solution to this problem was to ensure that client code which uses generics in the classes they invoke, never carries any information about generics in the compiled classfile. Because compiled client code never carries information about generics anyways, people were not forced to change their old code shown in Listing-3 to code shown in Listing-4. Thus library developers were free to add generics to their code without worrying about breaking old code which used their library.
To summarize, type erasure is the process by which type parameters and arguments are removed from the compiled bytecode, thus enabling library developers to port their libraries to use generics, without worrying about breaking old code.
Resources:
* A tutorial (pdf) on Java generics
* Oracle’s tutorial on type erasure
* Bruce Eckel’s excellent article on type erasure
Great post!
I came across an interesting article critiquing Java generics. The article as well as it's comments are a good read.
Article: http://www.artima.com/weblogs/viewpost.jsp?thre…
Thanks, I am glad you liked it.
Yes I too have come across several opinions on generics and type erasure in Java.
In my experience I feel that the strength of type erasure is also it's weakness. It ensures backwards compatibility by not breaking old code which did not use generics, but this also allows us to write new code which bypasses having to specify type information.
Regarding generics in particular, I feel that it does add a certain verbosity to the language which could have been simplified.
Can you outline what kind of problems this can cause? (I hear a lot of people moan about Java's type erasure.)
Good article and good explanation of type erasure.I believe it can help people understand type erasure and the usefulness of generics!Good job! 🙂