How to get the generic type at runtime?

There’s some confusion here. Due to type erasure you can’t get type information from the runtime parameterized type like:

Class<E> cls = E.getClass(); // Error.
E e = new E(); // Error.

However, you can obtain compiletime parameterized type information from class, field and method declaration by ParameterizedType#getActualTypeArguments().

abstract class AbstractExecutor<E> {

    public void execute() throws Exception {
        List<E> list = new ArrayList<E>();
        Class<E> cls = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        E e = cls.getConstructor(String.class).newInstance("Gate");
        list.add(e);
        System.out.println(format(list));
    }

    // ...
}

Update: as to whether this is recommended or not, although this will work, this is sensitive to runtime problems whenever minor changes in the class declaration occur. You as developer should document it properly. As a completely different alternative, you can make use of polymorphism.

abstract class AbstractExecutor<E> {

    public void execute() throws Exception {
        List<E> list = new ArrayList<E>();
        E e = create("Gate");
        list.add(e);
        System.out.println(format(list));
    }

    public abstract E create(String name);

    // ...
}

and implement UserExecutor accordingly.

class UserExecutor extends AbstractExecutor<User> {

    @Override
    public User create(String name) {
        return new User(name);
    }

    // ...
}

Leave a Comment