JAVA - 获取 class 的通用实现

JAVA - Get generic implementation of a class

假设我有一个抽象 class 定义 Generic Type。所有子classes 都将实现此通用类型。

我可以通过声明一个强制 subclass 到 return 该类型的抽象方法来实现。但是有没有更优雅的方法可以直接从 subclass 的 'Class' 对象定义中实现这一点?

public class GenericTest {
    public static void main(String[]args) throws Exception{
        Class strClass = ClazzImplString.class;
        Class intClass = ClazzImplInteger.class;

        Class implTypeStr = ((AbsClazz)strClass.getConstructor().newInstance()).getGenericType();
        Class implTypeInt = ((AbsClazz)intClass.getConstructor().newInstance()).getGenericType();

        System.out.println("implTypeStr: " + implTypeStr);
        System.out.println("implTypeInt: " + implTypeInt);
    } 
}
abstract class AbsClazz<GenericType> {
    abstract Class getGenericType();
}

class ClazzImplString extends AbsClazz<String> {
    public ClazzImplString() {}    
    @Override  Class getGenericType() {return String.class;}
}
class ClazzImplInteger extends AbsClazz<Integer> {
    public ClazzImplInteger() {}    
    @Override Class getGenericType() {return Integer.class;}
}

提前致谢

您可以将抽象方法的 return 类型设置为 Class,使用通用类型进行参数化:

abstract class AbsClazz<T> {
    abstract Class<T> getGenericType();
}

然后,在你的子class中,你将被迫实现一个方法,returns [=]中提供的类型19=]定义。例如:

class ClazzImplString extends AbsClazz<String> {
    public ClazzImplString() {}    
    @Override Class<String> getGenericType() {return String.class;}
}

是的,您可以使用 reflection

ParameterizedType genericSuperclass = (ParameterizedType) ClazzImplString.class.getGenericSuperclass();
Class<?> clazz = (Class<?>) genericSuperclass.getActualTypeArguments()[0];
System.out.println(clazz); // prints class java.lang.String

这是一个疯狂的反射技巧:

import java.lang.reflect.ParameterizedType;

class GenericClazz<T> {
    public Class<T> getType() {
        return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }
}

(来源 - 我的旧项目之一:link

您可以避免每个子类型上的 getGenericType 从子类型中获取 ParameterizedType

示例如下:

public abstract class AbsClazz<E extends Serializable> { }

public class ClazzImplInteger extends AbsClazz<Integer> { }

public class ClazzImplString extends AbsClazz<String> { }

public class GenericTest {

    public static void main(String[] args) {
        System.out.println("implTypeStr: " + getTypeFromGenericClass(ClazzImplString.class, 0));
        System.out.println("implTypeInt: " + getTypeFromGenericClass(ClazzImplInteger.class, 0));
    }

    public static Class<?> getTypeFromGenericClass(final Class<?> genericType, final Integer index) {
        final ParameterizedType type = (ParameterizedType) genericType.getGenericSuperclass();
        return (Class<?>) type.getActualTypeArguments()[index];
    }

}

此示例将打印:

implTypeStr: class java.lang.String
implTypeInt: class java.lang.Integer