在Java中获取泛型的Class对象
在Java中获取泛型的Class对象是一个常见但有些棘手的问题,因为Java的泛型在运行时会被擦除(type erasure),以下是几种获取泛型Class对象的方法:

使用Class.getGenericSuperclass()
这是最常用的方法,可以获取父类的泛型信息:
public class MyClass<T> {
public Class<T> getGenericClass() {
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
return (Class<T>) genericSuperclass.getActualTypeArguments()[0];
}
}
使用示例:
public class StringMyClass extends MyClass<String> {
public static void main(String[] args) {
StringMyClass instance = new StringMyClass();
Class<String> stringClass = instance.getGenericClass();
System.out.println(stringClass); // 输出: class java.lang.String
}
}
使用Class.getGenericInterfaces()
如果类实现了泛型接口,可以使用此方法:
public class MyClass implements MyInterface<String> {
public Class<String> getGenericClass() {
ParameterizedType genericInterface = (ParameterizedType) getClass().getGenericInterfaces()[0];
return (Class<String>) genericInterface.getActualTypeArguments()[0];
}
}
通过反射获取字段/方法的泛型类型
可以获取字段或方法参数的泛型类型:

public class GenericFieldExample<T> {
private T value;
public Class<T> getValueType() throws NoSuchFieldException {
Field field = GenericFieldExample.class.getDeclaredField("value");
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
return (Class<T>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
}
return null;
}
}
使用TypeToken(Google Guava)
Guava库提供了更优雅的方式处理泛型类型:
import com.google.common.reflect.TypeToken;
public class TypeTokenExample<T> {
private TypeToken<T> typeToken = new TypeToken<T>(getClass()) {};
public Class<T> getGenericClass() {
return typeToken.getRawType();
}
}
使用示例:
public class StringExample extends TypeTokenExample<String> {
public static void main(String[] args) {
StringExample example = new StringExample();
System.out.println(example.getGenericClass()); // 输出: class java.lang.String
}
}
注意事项
- 泛型类型在运行时会被擦除,所以只能获取到编译时保留的信息
- 这些方法通常在子类中才能正确获取泛型参数
- 对于复杂的嵌套泛型,处理会更复杂
- 如果泛型参数是通配符(如),可能无法获取具体的类型
完整示例
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class GenericTypeExample<T> {
public Class<T> getGenericType() {
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] typeArgs = parameterizedType.getActualTypeArguments();
return (Class<T>) typeArgs[0];
}
return null;
}
public static void main(String[] args) {
StringExample stringExample = new StringExample();
System.out.println("String type: " + stringExample.getGenericType());
IntegerExample integerExample = new IntegerExample();
System.out.println("Integer type: " + integerExample.getGenericType());
}
}
class StringExample extends GenericTypeExample<String> {}
class IntegerExample extends GenericTypeExample<Integer> {}
输出:
String type: class java.lang.String
Integer type: class java.lang.Integer
选择哪种方法取决于你的具体需求和项目环境,如果项目中已经使用了Guava,推荐使用TypeToken;否则,使用反射方法也是可行的。
