Wednesday, December 15, 2010

Type erasure in Java.

Probably every Java developer knows what type erasure is. In Oracle tutorial on Type Erasure we can read:

When a generic type is instantiated, the compiler translates those types by a technique called type erasure — a process where the compiler removes all information related to type parameters and type arguments within a class or method. Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics.

The generic types are only for the compile time - after the type checking they are removed and gone for good, for sake of legacy code. Are they really? Let's have a look at the code I just wrote:

import java.lang.reflect.Field;   
import java.lang.reflect.ParameterizedType;   
import java.lang.reflect.Type;   
  
class P1 {}   
class P2 {}   
class P3 {}   
  
class A<T1, T2, T3> { }   
  
public class Gen2 {    

    A<P1, Integer, P3> genTest = new A<P1, Integer, P3>();   
    public static void main(String[] args) throws Exception {      
        ParameterizedType genTestField = (ParameterizedType)Gen2.class.getDeclaredField("genTest").getGenericType();   
        for(Type type : genTestField.getActualTypeArguments() ) {   
            System.out.println(type);   
        }   
    }   


In the above code, we define a generic class A that can be parametrized - in the line 13 we instantiate this class with parameters P1, Integer and P3. And now,
through a reflection of Gen2 class and methods getDeclaredField(String) and getGenericType() we can elicit the parameters used during instantiating generic class A!
The code will print:
class P1
class java.lang.Integer
class P3
So in this way we can get exactly the generic parameters that were used. How this can be accomplished? As I already wrote, through a reflection. When we open a compiled Gen2.class file we can see a section "Signature":
Signature LA<LP1;Ljava/lang/Integer;LP3;>;
which shows the types that we were interested in. So apparently it seems that this information is not completely removed after the compilation time. From the bytecode yes, but in the .class file the information is still available!
In my opinion it's a very interesting and important example especially when we can read in many places that after the compilation we can't get the parameters anymore! Hope it was at least a little bit inspiring and encouraged you to read more on the reflection mechanism.

No comments:

Post a Comment