How to create an instance just by generic type T

This question already has an answer here:

  • Create instance of generic type in Java?

    23 answers

I want to create an instance just by defining the type for a generic class

public abstract class Base<T> {
    private final T genericTypeObject;

    protected Base(){
          //Create instance of T here without any argument

    }
}

So that I just can call the default constructor:

public class Child extends Base<SomeClass>{
    public Child () {
        super();
    }
}

and the Base-class implementation will create me an instance of the GenericType.

The generic information will be erased at compile time, so there will be no T anymore during runtime (you loose the information). Thats why you somewhere will need a Class<> to store the information.


The most clean & simple solution form my point of view is to pass in the class to to the constructor. I know you requested it to be without any constructor argument, but I do not think this is possible.


Code Sample

public abstract class AbstractBase<T> {

    private final T genericTypeObject;

    protected Base(Class<T> type){
        try {
            genericTypeObject = type.newInstance();
        } catch (InstantiationException e) {
            // Handle
        } catch (IllegalAccessException e) {
            // Handle
        }
    }
}

public class Child extends Base<SomeClass> {

    public Child () {
        super(SomeClass.class);
    }
}

Alternative Solution

Using a Supplier (thanks for the comment @Jorn Vernee):

public abstract class AbstractBase<T> {

  private final T genericTypeObject;

  public AbstractBase(Supplier<T> supplier) {
    genericTypeObject = supplier.get();
  }
}

public class Child extends AbstractBase<SomeClass> {

  public Child() {
    super(SomeClass::new);
  }
}

You must have access to the class to create an instance, so creating an instance without an argument is not possible. You must pass a Class<T>.

UPDATE:

See @JDC’s answer.

At runtime this returns me a Class instance:

public static Class<?> getGenericClassOfType(Object object){
        Class<?> clazz = (Class<?>) ((ParameterizedType) object.getClass() .getGenericSuperclass()).getActualTypeArguments()[0];
        return clazz;
}

and afterwards I can initiate it with:

public static <T> T getDefaultInstance(Class<T> clazz) throws IllegalAccessException, InvocationTargetException, InstantiationException {
    T instance = null;
    Constructor<T>[] constructors = (Constructor<T>[]) clazz.getDeclaredConstructors();
    Constructor<T> constructor = null;
    for (Constructor cstr : constructors) {
        //Only if default constructor
        if (cstr.getParameters().length == 0) {
            constructor = (Constructor<T>) cstr;
            break;
        }
    }
    if (constructor != null) {
        constructor.setAccessible(true);
        instance = constructor.newInstance();
    }

    return instance;
}

so the code in my base constructor looks like:

public abstract class BaseScene<T extends SceneController> {
    private final static Logger LOGGER =  LogManager.getLogger(BaseScene.class);

    private final T sceneController;

    //public T getSceneController() {
    //    return sceneController;
    //}

    protected BaseScene(){
        T newInstance = null;
        try {
            Class<T> clazz = (Class<T>)ReflectionHelper.getGenericClassOfType(this);
            newInstance = ReflectionHelper.getDefaultInstance(clazz);
        } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
            LOGGER.error("Error while trying to initiate BaseScene",e);
        }
        sceneController = newInstance;
    }
}

which works perfectly as I tested it.