java Java的获取编译时泛型工具

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java Java的获取编译时泛型工具相关的知识,希望对你有一定的参考价值。

package cc.yihy.util;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

/**
 * 分析编译时泛型参数,获取class
 *
 * @author yihy Create at 2018/11/12
 */
public class GenericToClassUtil {

    private static Map<String, Class<?>> classMap = new ConcurrentHashMap<>();

    public static <T, A> Class<T> getGeneric(Class<? extends A> thisClass, Class<A> superClass, int genericIndex) {
        String key = thisClass.getName() + "_" + superClass.getName() + "_" + genericIndex;
        return (Class<T>) classMap.computeIfAbsent(key, k -> getT(thisClass, superClass, genericIndex));
    }

    private static <T, A> Class<T> getT(Class<? extends A> thisClass, Class<A> superClass, int genericIndex) {
        ParameterizedType type = findTypeBySuperClass(thisClass, superClass);
        return getClassByIndex(thisClass, genericIndex, type);
    }

    private static <T, A> Class<T> getClassByIndex(Class<? extends A> thisClass, int genericIndex,
            ParameterizedType type) {
        Type actualTypeArgument = type.getActualTypeArguments()[genericIndex];
        validTypeIsClass(thisClass, actualTypeArgument);
        return (Class<T>) actualTypeArgument;
    }

    private static <A> void validTypeIsClass(Class<? extends A> thisClass, Type actualTypeArgument) {
        if (actualTypeArgument instanceof Class) {
            return;
        }
        throw new RuntimeException(MessageFormat.format("不支持自动推断运行时的泛型,请重写 {0} 类的获取泛型类的方法", thisClass.getName()));
    }

    private static <A> Type[] getGenericType(Class<? extends A> thisClass, Class<A> superClass) {
        Type[] generic;
        if (superClass.isInterface()) {
            generic = thisClass.getGenericInterfaces();
        } else {
            generic = new Type[1];
            generic[0] = thisClass.getGenericSuperclass();
        }
        return generic;
    }

    private static <A> ParameterizedType findTypeBySuperClass(Class<? extends A> thisClass, Class<A> superClass) {
        Type[] generic = getGenericType(thisClass, superClass);

        Optional<ParameterizedType> typeOptional = Stream.of(generic).filter(t -> t instanceof ParameterizedType)
                .map(t -> (ParameterizedType) t).filter(type -> Objects.nonNull(type.getRawType()))
                .filter(type -> type.getRawType().equals(superClass)).findAny();
        if (!typeOptional.isPresent()) {
            throw buildException(generic, thisClass, superClass);
        }
        return typeOptional.get();
    }

    private static <A> RuntimeException buildException(Type[] generic, Class<? extends A> thisClass,
            Class<A> superClass) {
        Optional<? extends Class<?>> associationClass = findAssociationClass(generic, thisClass, superClass);
        if (!associationClass.isPresent()) {
            return new IllegalStateException(
                    MessageFormat.format("{0} 没有直接继承/实现 {1}\n解决办法: 1, {0} 重写 {1} 中的获取泛型类的方法  2, {0} 直接继承或实现 {1}",
                            thisClass.getName(), superClass.getName()));
        }
        String name = associationClass.get().getName();
        return new RuntimeException(MessageFormat.format(
                "{1} 需要重写 {2} 的分析泛型类方法\n解决办法: 1, 重写 {1} 类的泛型推断方法  2, 重写 {0} 的泛型推断方法  3, 让 {0} 直接继承或实现 {2}",
                thisClass.getName(), name, superClass.getName()));
    }

    /**
     * 查找一个类,既实现了superClass,又是thisClass的父类
     *
     * @param            <A> 基类
     * @param generic    this类的父类信息
     * @param thisClass  当前实现类
     * @param superClass this类的基类
     * @return 实现了superClass,又是thisClass父类的类
     */
    private static <A> Optional<? extends Class<?>> findAssociationClass(Type[] generic, Class<? extends A> thisClass,
            Class<A> superClass) {
        List<Type> list = new ArrayList<>(Arrays.asList(generic));
        if (superClass.isInterface()) {
            list.add(thisClass.getGenericSuperclass());
        }
        Optional<? extends Class<?>> any = list.stream().filter(t -> t instanceof ParameterizedType)
                .map(t -> (ParameterizedType) t).filter(type -> Objects.nonNull(type.getRawType()))
                .map(type -> (Class<?>) type.getRawType()).filter(superClass::isAssignableFrom).findAny();
        return any;
    }
}

以上是关于java Java的获取编译时泛型工具的主要内容,如果未能解决你的问题,请参考以下文章

编译时泛型类型大小检查

c# 使用运行时泛型类型调用委托

java泛型与通配符

Google Guava 反射机制工具类

java泛型

如何在运行时获取泛型的类型