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}}
public class Foo<T> {
private Class<T> type;public Foo(Class<T> type) {this.type = type;}
public Class<T> getType() {return type;}
public T newInstance() {return type.newInstance();}}
import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;
import java.util.ArrayDeque;import java.util.Deque;import java.util.NoSuchElementException;
/*** Captures and silently ignores stack exceptions upon popping.*/public abstract class SilentStack<E> extends ArrayDeque<E> {public E pop() {try {return super.pop();}catch( NoSuchElementException nsee ) {return create();}}
public E create() {try {Type sooper = getClass().getGenericSuperclass();Type t = ((ParameterizedType)sooper).getActualTypeArguments()[ 0 ];
return (E)(Class.forName( t.toString() ).newInstance());}catch( Exception e ) {return null;}}}
然后:
public class Main {// Note the braces...private Deque<String> stack = new SilentStack<String>(){};
public static void main( String args[] ) {// Returns a new instance of String.String s = stack.pop();System.out.printf( "s = '%s'\n", s );}}
public <T> T yourMethodSignature(Class<T> type) {
// get some object and check the type match the given typeObject result = ...
if (type.isAssignableFrom(result.getClass())) {return (T)result;} else {// handle the error}}
import java.lang.reflect.TypeVariable;
public static <T> Class<T> getGenericClass() {__<T> instance = new __<T>();TypeVariable<?>[] parameters = instance.getClass().getTypeParameters();
return (Class<T>)parameters[0].getClass();}
// Generic helper class which (only) provides type information. This avoids the// usage of a local variable of type T, which would have to be initialized.private final class __<T> {private __() { }}
public class MyClass<A, B, C> {
private Class<A> aType;
private Class<B> bType;
private Class<C> cType;
// Getters and setters (not necessary if you are going to use them internally)
}
然后您可以创建一个泛型方法,该方法根据泛型定义的索引返回类型:
/*** Returns a {@link Type} object to identify generic types* @return type*/private Type getGenericClassType(int index) {// To make it use generics without supplying the class typeType type = getClass().getGenericSuperclass();
while (!(type instanceof ParameterizedType)) {if (type instanceof ParameterizedType) {type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();} else {type = ((Class<?>) type).getGenericSuperclass();}}
return ((ParameterizedType) type).getActualTypeArguments()[index];}
最后,在构造函数中只需调用方法并发送每种类型的索引。完整的代码应该如下所示:
public class MyClass<A, B, C> {
private Class<A> aType;
private Class<B> bType;
private Class<C> cType;
public MyClass() {this.aType = (Class<A>) getGenericClassType(0);this.bType = (Class<B>) getGenericClassType(1);this.cType = (Class<C>) getGenericClassType(2);}
/*** Returns a {@link Type} object to identify generic types* @return type*/private Type getGenericClassType(int index) {
Type type = getClass().getGenericSuperclass();
while (!(type instanceof ParameterizedType)) {if (type instanceof ParameterizedType) {type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();} else {type = ((Class<?>) type).getGenericSuperclass();}}
return ((ParameterizedType) type).getActualTypeArguments()[index];}}
Class<CustomViewModel<String>> clazz = new GenericClass<CustomViewModel<String>>().getRawType();CustomViewModel<String> viewModel = viewModelProvider.get(clazz);
泛型类型类
class GenericClass<T>(private val rawType: Class<*>) {
constructor():this(`$Gson$Types`.getRawType(object : TypeToken<T>() {}.getType()))
fun getRawType(): Class<T> {return rawType as Class<T>}}
import org.junit.jupiter.api.Test;
import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;
import static org.junit.jupiter.api.Assertions.assertEquals;import static org.junit.jupiter.api.Assertions.assertThrows;
public class GenericTest {
/*** only this will work!*/@Testvoid testGetGenericTypeClassFromChildClassWithSpecifiedType() {TestClassWithSpecifiedType parent = new TestClassWithSpecifiedType();assertEquals(SomeGenericType.class, parent.getGenericTypeClass());}
/*** won't work!*/@Testvoid testGetGenericTypeClassFromChildClassWithUnspecifiedType() {TestClassWithUnspecifiedType<SomeGenericType> parent = new TestClassWithUnspecifiedType<>();assertThrows(IllegalStateException.class, parent::getGenericTypeClass);}
/*** won't work*/@Testvoid testGetGenericTypeClassWithUnspecifiedType() {SomeGenericTypedClass<SomeGenericType> parent = new SomeGenericTypedClass<>();assertThrows(IllegalStateException.class, parent::getGenericTypeClass);}
/*** won't work* returns object instead!*/@Testvoid testGetLoadedClassFromObject() {Foo<SomeGenericType> foo = new Foo<>();Class<?> barClass = foo.getBarClass();assertEquals(SomeGenericType.class, barClass);}
/*** A class that has specified the type parameter*/public static class TestClassWithSpecifiedType extends AbstractGenericTypedClass<SomeGenericType> {
}
/*** A class where the type parameter will be specified on demand** @param <T>*/public static class TestClassWithUnspecifiedType<T> extends AbstractGenericTypedClass<T> {
}
/*** An abstract class, because otherwise finding the parameter will not work*/@SuppressWarnings("unchecked")public static abstract class AbstractGenericTypedClass<T> {@SuppressWarnings("unchecked")public Class<T> getGenericTypeClass() {try {String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();Class<?> clazz = Class.forName(className);return (Class<T>) clazz;} catch (Exception e) {throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");}}}
/*** A typed class without abstract super class** @param <T>*/public static class SomeGenericTypedClass<T> {@SuppressWarnings("unchecked")public Class<T> getGenericTypeClass() {try {String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();Class<?> clazz = Class.forName(className);return (Class<T>) clazz;} catch (Exception e) {throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");}}}
/*** Some generic type - won't work with primitives such as String, Integer, Double!*/public static class SomeGenericType {
}
public static class Foo<T> {// The class:private final Class<?> barClass;
public Foo() {try {// Im giving it [0] cuz Bar is the first TypeParamType[] bounds = getClass().getTypeParameters()[0].getBounds();// Here, we get the class now:barClass = Class.forName(bounds[0].getTypeName());} catch (ClassNotFoundException e) {// will never happen!throw new Error("Something impossible happened!", e);}}
public Class<?> getBarClass() {return barClass;}}}