Restrictions on Generics in java and reflection
I was reading this about generics and their restrictions.
Cannot Create Instances of Type Parameters
You cannot create an instance of a type parameter. For example, the following code causes a compile-time error:
public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}
As a workaround, you can create an object of a type parameter through reflection:
public static <E> void append(List<E> list, Class<E> cls) throws Exception {
E elem = cls.newInstance(); // OK
list.add(elem);
}
You can invoke the append method as follows:
List<String> ls = new ArrayList<>();
append(ls, String.class);
I am somewhat confused. I understand why it isn't allowed because that new E() will just turn into new object() because of type erasure, but why doesn't the same thing happen in class.newInstance? I mean it uses the type parameter E, so wouldn't it end up with the same problem? Could someone please explain (I know I have to add the try-catch to get it to compile).
Thanks in advance!
As you have noted, the type parameter E
is just something used by the compiler, it's not instantiated with the generic and cannot be used at run-rime. The parameter cls
, on the other hand, is a real thing. It is an object passed in at run-time that has all its type information there to be reflected upon. The E
in cls
's type (recall Class<E> cls
) will be type-erased (after all, Class
is just another generic) but the object cls
will carry on the information about its type.
It will work because the programer calling the method will have to pass a Class<E>
instance as a parameter (the type of this instance will be checked compile-time before type erasure). This instance will be able at runtime to call the right constructor because it is able to determine its runtime type, which was not possible without an actual instance in the first snippet.
下一篇: 对java中的泛型和反射的限制