Class Object of Generic Class (Java)

How do I get a class instance of generic type T?

The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. I suggest reading the chapter about type erasure in the Java Tutorial for more details.

A popular solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.

class Foo<T> {
final Class<T> typeParameterClass;

public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}

public void bar() {
// you can access the typeParameterClass here and do whatever you like
}
}

Get Class-object representation of generic parameter in Java

The reason why

Class<T> persistentClass = (Class<T>)
((ParameterizedType)getClass().getGenericSuperclass())
.getActualTypeArguments()[0];

works was because the superclass of this happens to be a class with a parameterised type as its superclass. Therefore you can get the actual type arguments of that type. The type parameters of superclasses are stored as metadata in the class file if you write them in the source file.

However, in your case, whatever is passed to the onCatch parameter is not going to have a superclass of Consumer<T>. After all, Consumer<T> is not a class! You need to use getGenericInterfaces and find the one that has the name that starts with java.util.function.Consumer.

System.out.println(
// I've assumed the Consumer interface is the first one, to keep it brief
((ParameterizedType)onCatch.getClass().getGenericInterfaces()[0])
.getActualTypeArguments()[0]
);

This would work if the caller calls onCatch like this:

onCatch(new Consumer<RuntimeException>() {
@Override
public void accept(RuntimeException e) {

}
});

The anonymous class will implement Consumer<RuntimeException>, and this information will be written to the class file representing the anonymous class.

However, if you use a lambda:

onCatch((RuntimeException e) -> {});

Then only a method like this is generated in the same class as the caller:

private static void lambda$caller$0(RuntimeException e) {

}

and at runtime, invokedynamic is used to create an instance that implements Consumer, and this is the bad news: the type parameter RuntimeException is not part of the generated class for this instance, for whatever reason.

The only way you can find RuntimeException now then, is if you somehow know who the caller is, and find the lambda$caller$0 method, and look at its parameter.

That said, everything I've wrote so far is pretty much all implementation detail, and I wouldn't use any of that in production code. I would say you should just add a Class<E> parameter:

onCatch(RuntimeException.class, e -> {});

It doesn't look that different on the caller's side anyway.

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);
}

Specifying a generic type in java from Class object

<T extends Number> ArrayList<T> createAList(Class<T> type)  
{
ArrayList<T> toReturn = new ArrayList<>();
return toReturn;
}

ArrayList<Integer> intList = createAList(Integer.class);

Java: Get ClassT object of generic class

As mentioned by Pshemo in a comment you can't really do this in Java directly because of type erasure. However, a couple of ways to achieve that would be to take the class as a parameter of the someFunction. E.g.

public class MyObject<T extends SomeClass1, S extends SomeClass2> {
// ....
public void someFunction(Class<T> clazz) {
ExternalClass.doSomething(clazz); // problem here!
}
}

Then you would push the problem further out.

In case you have a field of type T that has an object of that type you could use that to pass to the ExternalClass, e.g.

public class MyObject<T extends SomeClass1, S extends SomeClass2> {
private T t;
public MyObject(T t) {
this.t = t;
}

public void someFunction() {
ExternalClass.doSomething(t.getClass()); // problem here!
}
}

A third option if you can not alter the signature of neither the constructor nor the someFunction would be to maldate a call to a setter method that you control, e.g.

public class MyObject<T extends SomeClass1, S extends SomeClass2> {
private T t;

public void someFunction() {
ExternalClass.doSomething(t.getClass()); // problem here!
}

public void setClazz(T t) {
this.t = t;
}
}

You could expand on this and let the caller register a callback that you use to resolve the class, but that might be overkill...



Related Topics



Leave a reply



Submit