Java 泛型 T.class 的获取

2,462 阅读2分钟

在使用策略模式设计了一个抽象服务类,该类有一个泛型,在程序中又需要该泛型指向的class,代码参考如下:

public abstract class AbstractService<T> {
    private Class<T> tclazz;
    public Class<T> getTClass(){
        return tclazz;
    }
    
    public AbstractService() {
        //tclazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        ParameterizedType parameterizedType = getParameterizedType(getClass());
        Type[] params = parameterizedType.getActualTypeArguments();
        tclazz = getClazz(params[0]);
    }

    /**
     * 递归获取 ParameterizedType
     * (对于一个实现类,它有可能是父类的父类才是 AbstractService)
     *
     */
    private ParameterizedType getParameterizedType(Type type){
        if(type instanceof ParameterizedType){
            return (ParameterizedType) type;
        }else if(type instanceof Class){
            return getParameterizedType((((Class<?>) type).getgetGenericSuperclass()));
        }else{
            return null;
        }
    }
    /**
     * 递归获取 Class
     * (对于一个实现类,它有可能是父类的父类才是 AbstractService)
     *
     */
    private Class getClazz(Type type){
        if(type instanceof ParameterizedType){
            Type rawType = ((ParameterizedType) type).getRawType();
            return getClazz(rawType);
        }else{
            return (Class) type;
        }
    }
}

几个重要的方法

public Type getGenericSuperclass()

用来返回表示当前Class 所表示的实体(类、接口、基本类型或 void)的直接超类的Type。如果这个直接超类是参数化类型的,则返回的Type对象必须明确反映在源代码中声明时使用的类型。比如:

import java.lang.reflect.ParameterizedType; 
public class AAService extends AbstractService<Integer>{ 
  public static void main(String[] args) { 
    System.out.println(((ParameterizedType)new AAService().getClass().getGenericSuperclass())); 
  } 
}

则输出结果即为:

AbstractService

如果此Class代表的是Object 类、接口、基本类型或 void,则返回 null。。如果此对象表示一个数组类,则返回表示 Object 类的 Class 对象。

public Type[] getGenericInterfaces()

与上面那个方法类似,只不过Java的类可以实现多个接口,所以返回的Type必须用数组来存储。

以上两个方法返回的都是Type对象或数组,在我们的这个话题中,Class都是代表的参数化类型,因此可以将Type对象Cast成ParameterizedType对象。

ParameterizedType

ParameterizedType对象有一个方法, getActualTypeArguments()。

public Type[] getActualTypeArguments() 用来返回一个Type对象数组,这个数组代表着这个Type声明中实际使用的类型。

超类中获取T.class

子类在继承具有泛型的超类时,会自动调用超类的构造方法。在此超类的构造方法中,调用的getClass返回的是子类的Class类型