Created
November 16, 2018 06:10
-
-
Save jianyun8023/ebffbf7d64513e40039734fa78395843 to your computer and use it in GitHub Desktop.
Java获取编译时泛型工具
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
可以获取编译时泛型的class,父类可以是接口或类,子类需要声明出具体的泛型。