acejazz acejazz - 5 months ago 10
Java Question

How is the generic java erasure affecting the usage of newInstance()?

Based on the java documentation:


During the type erasure process, the Java compiler erases all type
parameters and replaces each with its first bound if the type
parameter is bounded, or Object if the type parameter is unbounded.


Now, the thing is, with a class like that:

public class MyCreator<T> {
Class<T> kind;

MyCreator(Class<T> kind) {
this.kind = kind;
}

void printInstanceClass() throws Exception{
System.out.println(kind.newInstance().getClass());
}

public static void main(String[] args) throws Exception{
MyCreator<String> myCreator = new MyCreator<String>(String.class);

myCreator.printInstanceClass();
}
}


the
printInstanceClass()
method is printing actually "class java.lang.String".

If the compiler is replacing T inside of the class with Object, I guess that also the information on Class associated with
kind
is removed and replaced with Class. So, how can the
newInstance()
method return a String instance instead of an Object one?

Answer

The tricky part is the String.class parameter. It's not a type parameter, but a plain old param, like String[] args. So, the Class<T> kind will be String.class thus the printInstanceClass() can access it at runtime.

It's a common practice, suggested in Effective Java too.

So after type erasure this code is logically equivalent to this one:

public class MyCreator { Class kind; // this will be String.class at runtime

MyCreator(Class<?> kind) {
    this.kind = kind; 
}

void printInstanceClass() throws Exception{ 
    System.out.println(kind.newInstance().getClass());
}

public static void main(String[] args) throws Exception{ 
    MyCreator myCreator = new MyCreator(String.class);

    myCreator.printInstanceClass();
} 

}

Comments