Instantiating a Generic Class in Java

Instantiating a generic class in Java

One option is to pass in Bar.class (or whatever type you're interested in - any way of specifying the appropriate Class<T> reference) and keep that value as a field:

public class Test {
public static void main(String[] args) throws IllegalAccessException,
InstantiationException {
Generic<Bar> x = new Generic<>(Bar.class);
Bar y = x.buildOne();
}
}

public class Generic<T> {
private Class<T> clazz;

public Generic(Class<T> clazz) {
this.clazz = clazz;
}

public T buildOne() throws InstantiationException, IllegalAccessException {
return clazz.newInstance();
}
}

public class Bar {
public Bar() {
System.out.println("Constructing");
}
}

Another option is to have a "factory" interface, and you pass a factory to the constructor of the generic class. That's more flexible, and you don't need to worry about the reflection exceptions.

Instantiating generics type in java

public class Abc<T> {
public T getInstanceOfT(Class<T> aClass) {
return aClass.newInstance();
}
}

You'll have to add exception handling.

You have to pass the actual type at runtime, since it is not part of the byte code after compilation, so there is no way to know it without explicitly providing it.

Instantiate a generic class T object and return it

Generic types are a compile-time notation for ensuring type safety. They are erased at runtime.

This means T and U do not exist at runtime. Which is why you can’t instantiate them.

You can, however, pass in the constructors yourself:

public class Button<T, U> {
private final Supplier<? extends T> tConstructor;
private final Supplier<? extends U> uConstructor;

public Button(Supplier<? extends T> tConstructor,
Supplier<? extends U> uConstructor) {

this.tConstructor = tConstructor;
this.uConstructor = uConstructor;
}

public T observe() {
return tConstructor.get();
}

public U click() {
return uConstructor.get();
}
}

And you can pass those constructors as method references:

public class FirstPage {
public Button<FirstPage, SecondPage> buttonOnFirstPage =
new Button<>(FirstPage::new, SecondPage::new);
}

Java Instantiate Generic Type

Java pattern to deal with this is to store Class<E>, and use its newInstance method, as follows:

// Class<E> object will be used to create new instances
private final Class<E> stateClass;
// Users will pass the class to StateMachine's constructor
public StateMachine(Entity entity, Class<E> stateClass) {
this.entity = entity;
this.stateClass = stateClass;
states = new ArrayMap<S, E>();
}

Now you can create new state objects as follows:

E state = stateClass.newInstance(); // Only parameterless constructors are supported
state.setEntity(entity);

How to instantiate a generic class that extends Number with a given double value?

First of all, your assumption that

Since each Number object should have a double value, when instantiating a new instance of type E I would like to give it a double value.

is not correct.

For example, how can you instantiate a Integer with a double value 1.5? Should it instantiate by rounding? By truncating? I can very well define a subclass of Number that doesn't even support arbitrary integer, like the following one:

public static class Zero extends Number {
@Override
public double doubleValue() {
return 0;
}

@Override
public float floatValue() {
return 0;
}

@Override
public int intValue() {
return 0;
}

@Override
public long longValue() {
return 0;
}
}

How do you instantiate a Zero with a double value like 1.5?

Since there is no universal logic that can instantiate an arbitrary subclass of Number with an arbitrary double value (this is the reason why Number don't have an constructor with a double argument), the only reasonable way is to ask the client to provide a factory that can fabricate an instance of a subclass of Number given an arbitrary double value with custom logic that applies to that specific subclass. Like the following:

  public class Foo<E extends Number> {

public static interface NumberFactory<T extends Number> {
T createByDoubleValue(double value);
}

private final NumberFactory<E> factory;

public Foo(NumberFactory<E> factory) {
this.factory = factory;
}

...
public void someMethod() {
... // some computation
// Because every Number has a doubleValue(),
// I would like to give newInstance a double value, how?
E instance = factory.createByDoubleValue(1.5);
}
}

To use Foo class, the client need to define the factory, like the following:

Foo<Float> foo = new Foo<>(new Foo.NumberFactory<Float>() {
@Override
public Float createByDoubleValue(double value) {
return new Float(value);
}
});

Java Generics and Reflection | How to instantiate a generic class

Class Class is also generic and you can infer the correct generic parameter from it:

public <E> Object getDAOForEntity(Class<E> c) {
try {
// ...
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
return new MyDAO<Integer,E>(emfa) {};
}
}

Instantiate generic type with constructor arguments?

Well, you can use for example getConstructor(Class...) to get a constructor which is other than the default no-argument one.

You'd have something like this:

import java.lang.reflect.*;

public class Handler<B extends Base & I1> {
private E instanceOfE = ...; // Not sure where you get the E from.
private Constructor<B> ctor;

public Handler(Class<B> ctype) {
if (Modifier.isAbstract(ctype.getModifiers())) {
throw new IllegalArgumentException(ctype + " is abstract");
}
if (!Modifier.isPublic(ctype.getModifiers())) {
throw new IllegalArgumentException(ctype + " is not public");
}
try {
ctor = ctype.getConstructor(E.class);
} catch (NoSuchMethodException x) {
throw new IllegalArgumentException(x);
}
Arrays.stream(ctor.getExceptionTypes())
.filter(x -> !RuntimeException.class.isAssignableFrom(x)
&& !Error.class.isAssignableFrom(x))
.findFirst()
.ifPresent(x -> throw new IllegalArgumentException(ctor + " declares a checked exception");
}

private B create() {
try {
return ctor.newInstance(instanceOfE);
} catch (InvocationTargetException x) {
Throwable cause = x.getCause();
if (cause instanceof RuntimeException)
throw (RuntimeException) cause;
if (cause instanceof Error)
throw (Error) cause;
// This won't happen because we checked for
// it in the constructor.
throw new RuntimeException(cause);
} catch (IllegalAccessException
| InstantiationException x) {
// These also won't happen because we checked
// for it in the constructor.
throw new RuntimeException(x);
}
}
}

However, I'm not all that convinced you need to use reflection. You can use lambda expressions and method references to do this sort of thing now and it's generally much better.

Instead of passing a class, you'd pass some sort of an Function<E, Base>:

public class Handler<B extends Base & I1> {
public Handler(Function<E, B> ctorFn) {
Base b = ctorFn.apply(instanceOfE);
}
}

And then you create new handlers with a method reference:

Handler<A1> h = new Handler<>(A1::new);

Reflection is fine and very powerful but it's not always the best way for this sort of thing nowadays.



Related Topics



Leave a reply



Submit