All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.shepherdviolet.glacimon.java.reflect.GenericClassUtils Maven / Gradle / Ivy

/*
 * Copyright (C) 2022-2022 S.Violet
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Project GitHub: https://github.com/shepherdviolet/glacimon
 * Email: [email protected]
 */

package com.github.shepherdviolet.glacimon.java.reflect;

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 泛型工具
 *
 * @author shepherdviolet
 */
public class GenericClassUtils {

    /**
     * 

获取一个类的父类/接口类的泛型实际类型. 无缓存.

* *

例如, 有个类A, 继承了类B(可以是多层), 类B定义了一个泛型, 而类A继承类B时指定了泛型, 获取这个泛型类型的代码如下:

* *
     *     GenericClassUtils.getActualClasses(A.class, B.class);
     * 
* *

例如, 有个类A, 实现了接口C(可以是多层), 类C定义了一个泛型, 而类A实现接口C时指定了泛型, 获取这个泛型类型的代码如下:

* *
     *     GenericClassUtils.getActualClasses(A.class, C.class);
     * 
* *

例如, 有个父类P, 会被其他类继承, 父类P定义了一个泛型, P想要获得自己的泛型最终被指定成了什么, 代码如下:

* *
     *     GenericClassUtils.getActualClasses(this.getClass(), P.class);
     * 
* *

在Spring中使用时, 对象有可能是个代理类, 在获取泛型前先获取代理类持有的实际类:

* *
     *     Class rawClass = AopProxyUtils.ultimateTargetClass(bean);
     * 
* * @param type 类 * @param targetGenericClass 泛型定义类, 指定要获取的泛型定义在哪个类/接口 * @return 不为空, NonNull, 类型: Class * @throws TargetGenericClassNotFoundException 异常情况: 给定类的父类或接口中找不到泛型定义类 */ public static Map> getActualClasses(Type type, Class targetGenericClass) throws TargetGenericClassNotFoundException { //检查 checkInput(type, targetGenericClass); if (targetGenericClass.getTypeParameters().length <= 0) { return new LinkedHashMap<>(); } //如果是数组类型/泛型数组类型(T[]), 脱壳处理 Type componentType = getComponentType(type); Type[] actualTypes; if (componentType instanceof Class) { //当前类 / 当前类对于子类的泛型对象 / 指定要获取的泛型定义在哪个类/接口 / 是否转成Class actualTypes = getActualTypes0((Class) componentType, null, targetGenericClass, true); } else if (componentType instanceof ParameterizedType) { //当前类 / 当前类对于子类的泛型对象 / 指定要获取的泛型定义在哪个类/接口 / 是否转成Class actualTypes = getActualTypes0((Class) ((ParameterizedType) componentType).getRawType(), componentType, targetGenericClass, true); } else { //不可能找到指定泛型类 throw new TargetGenericClassNotFoundException("The targetGenericClass '" + targetGenericClass.getName() + "' was not found in the super classes or interfaces of given type '" + type + "', We can only handle Class and ParameterizedType"); } //没找到指定泛型类 if (actualTypes == null) { throw new TargetGenericClassNotFoundException("The targetGenericClass '" + targetGenericClass.getName() + "' was not found in the super classes or interfaces of given type '" + type + "'"); } //过滤结果 filterActualTypes(actualTypes, true); //组装结果 Map> actualTypeMap = new LinkedHashMap<>(); TypeVariable[] typeVariables = targetGenericClass.getTypeParameters(); for (int i = 0 ; i < actualTypes.length ; i++) { actualTypeMap.put(typeVariables[i].getName(), (Class) actualTypes[i]); } return actualTypeMap; } /** *

获取一个类的父类/接口类的泛型实际类型. 无缓存.

* *

例如, 有个类A, 继承了类B(可以是多层), 类B定义了一个泛型, 而类A继承类B时指定了泛型, 获取这个泛型类型的代码如下:

* *
     *     GenericClassUtils.getActualTypes(A.class, B.class);
     * 
* *

例如, 有个类A, 实现了接口C(可以是多层), 类C定义了一个泛型, 而类A实现接口C时指定了泛型, 获取这个泛型类型的代码如下:

* *
     *     GenericClassUtils.getActualTypes(A.class, C.class);
     * 
* *

例如, 有个父类P, 会被其他类继承, 父类P定义了一个泛型, P想要获得自己的泛型最终被指定成了什么, 代码如下:

* *
     *     GenericClassUtils.getActualTypes(this.getClass(), P.class);
     * 
* *

在Spring中使用时, 对象有可能是个代理类, 在获取泛型前先获取代理类持有的实际类:

* *
     *     Class rawClass = AopProxyUtils.ultimateTargetClass(bean);
     * 
* * @param type 类 * @param targetGenericClass 泛型定义类, 指定要获取的泛型定义在哪个类/接口 * @return 不为空, NonNull, 类型: Class/ParameterizedType, 返回null表示未找到指定的声明泛型的类, 暂不支持GenericArrayType * @throws TargetGenericClassNotFoundException 异常情况: 给定类的父类或接口中找不到泛型定义类 */ public static Map getActualTypes(Type type, Class targetGenericClass) throws TargetGenericClassNotFoundException { //检查 checkInput(type, targetGenericClass); if (targetGenericClass.getTypeParameters().length <= 0) { return new LinkedHashMap<>(); } //如果是数组类型/泛型数组类型(T[]), 脱壳处理 Type componentType = getComponentType(type); Type[] actualTypes; if (componentType instanceof Class) { //当前类 / 当前类对于子类的泛型对象 / 指定要获取的泛型定义在哪个类/接口 / 是否转成Class actualTypes = getActualTypes0((Class) componentType, null, targetGenericClass, false); } else if (componentType instanceof ParameterizedType) { //当前类 / 当前类对于子类的泛型对象 / 指定要获取的泛型定义在哪个类/接口 / 是否转成Class actualTypes = getActualTypes0((Class) ((ParameterizedType) componentType).getRawType(), componentType, targetGenericClass, false); } else { //不可能找到指定泛型类 throw new TargetGenericClassNotFoundException("The targetGenericClass '" + targetGenericClass.getName() + "' was not found in the super classes or interfaces of given type '" + type + "', We can only handle Class and ParameterizedType"); } //没找到指定泛型类 if (actualTypes == null) { throw new TargetGenericClassNotFoundException("The targetGenericClass '" + targetGenericClass.getName() + "' was not found in the super classes or interfaces of given type '" + type + "'"); } //过滤结果 filterActualTypes(actualTypes, false); //组装结果 Map actualTypeMap = new LinkedHashMap<>(); TypeVariable[] typeVariables = targetGenericClass.getTypeParameters(); for (int i = 0 ; i < actualTypes.length ; i++) { actualTypeMap.put(typeVariables[i].getName(), actualTypes[i]); } return actualTypeMap; } /** * 输入检查 */ private static void checkInput(Type type, Class targetGenericClass) { if (type == null) { throw new NullPointerException("clazz is null"); } if (targetGenericClass == null) { throw new NullPointerException("targetGenericClass is null"); } if (targetGenericClass.isArray()) { throw new IllegalArgumentException("targetGenericClass is an array Class"); } } /** * 如果是数组, 或者泛型数组(T[]), 脱壳处理 */ private static Type getComponentType(Type type) { if (type instanceof Class) { // 如果是数组类型的话, 脱壳得到类 Class componentType = (Class) type; while (componentType.isArray()) { componentType = componentType.getComponentType(); } return componentType; } if (type instanceof GenericArrayType) { // 如果是泛型数组类型(例如: T[])的话, 脱壳得到T Type componentType = ((GenericArrayType) type).getGenericComponentType(); while (componentType instanceof GenericArrayType) { componentType = ((GenericArrayType) componentType).getGenericComponentType(); } return componentType; } return type; } /** * 过滤结果 */ private static void filterActualTypes(Type[] actualTypes, boolean preferRawClass) { for (int i = 0 ; i < actualTypes.length ; i++) { Type type = actualTypes[i]; if (type instanceof TypeVariable) { //到最后还是没有找到实际类型的话, 就视为Object.class actualTypes[i] = Object.class; } else if (type instanceof ParameterizedType) { //可以选择转成Class if (preferRawClass) { actualTypes[i] = ((ParameterizedType) type).getRawType(); } } else if (!(type instanceof Class)){ //其他类型均视为Object.class //未实现的情况: GenericArrayType, 泛型实际类型是一个数组类型, 例如: . 这个如果要实现, 得脱壳以后, 再创建一个GenericArrayType, 得复制GenericArrayTypeImpl的源码. actualTypes[i] = Object.class; } } } /** * 递归主逻辑 */ private static Type[] getActualTypes0(Class currentClass, Type currentGenericType, Class targetGenericClass, boolean preferRawClass) { Type[] actualTypes = null; //1.检查父类泛型 Type genericSuperClass = currentClass.getGenericSuperclass(); //genericSuperClass只可能是ParameterizedType或Class if (genericSuperClass instanceof ParameterizedType && targetGenericClass.equals(((ParameterizedType) genericSuperClass).getRawType())) { //找到指定类, 且确定了泛型 actualTypes = ((ParameterizedType) genericSuperClass).getActualTypeArguments(); } else if (targetGenericClass.equals(genericSuperClass)){ //找到指定类, 未确定泛型 TypeVariable[] targetTypeParameters = targetGenericClass.getTypeParameters(); actualTypes = new Type[targetTypeParameters.length]; for (int i = 0 ; i < targetTypeParameters.length ; i++) { actualTypes[i] = Object.class; } } else if (genericSuperClass != null && !genericSuperClass.equals(Object.class)) { //递归 actualTypes = getActualTypes0(currentClass.getSuperclass(), genericSuperClass, targetGenericClass, preferRawClass); } //2.检查接口泛型 if (actualTypes == null) { Type[] genericInterfaces = currentClass.getGenericInterfaces(); if (genericInterfaces != null && genericInterfaces.length > 0) { for (Type genericInterface : genericInterfaces) { //genericInterface只可能是ParameterizedType或Class if (genericInterface instanceof ParameterizedType && targetGenericClass.equals(((ParameterizedType) genericInterface).getRawType())) { //找到指定类, 且确定了泛型 actualTypes = ((ParameterizedType) genericInterface).getActualTypeArguments(); break; } else if (targetGenericClass.equals(genericInterface)){ //找到指定类, 未确定泛型 TypeVariable[] targetTypeParameters = targetGenericClass.getTypeParameters(); actualTypes = new Type[targetTypeParameters.length]; for (int i = 0 ; i < targetTypeParameters.length ; i++) { actualTypes[i] = Object.class; } break; } else { //递归 Class interface0 = null; if (genericInterface instanceof Class) { interface0 = (Class) genericInterface; } else if (genericInterface instanceof ParameterizedType) { interface0 = (Class) ((ParameterizedType) genericInterface).getRawType(); } if (interface0 != null) { actualTypes = getActualTypes0(interface0, genericInterface, targetGenericClass, preferRawClass); if (actualTypes != null) { break; } } } } } } //3.处理结果 if (actualTypes != null) { for (int i = 0 ; i < actualTypes.length ; i++) { Type type = actualTypes[i]; if (type instanceof TypeVariable) { if (currentGenericType instanceof ParameterizedType) { /* 如果发现有一个父类/接口的泛型没有在当前类被确定具体的类型, 就要查找当前类的泛型定义(就是public class Name ), 找到未确定的泛型对应当前类的第几个泛型定义, 然后在"当前类对于子类的泛型对象(currentGenericType)"中查找当前类定义的泛型 的实际类型. */ //获取当前类的泛型定义(就是public class Name ) TypeVariable[] currentTypeVariables = currentClass.getTypeParameters(); boolean matched = false; if (currentTypeVariables != null) { for (int offset = 0 ; offset < currentTypeVariables.length ; offset++) { //泛型名称相同, 找到对应位置 if (((TypeVariable) type).getName().equals(currentTypeVariables[offset].getName())) { Type[] currentActualTypeArgs = ((ParameterizedType) currentGenericType).getActualTypeArguments(); if (currentActualTypeArgs == null || offset >= currentActualTypeArgs.length) { //特殊: 正常情况是不可能找不到的, 会编译不通过, 这里简单的将类型赋值为Object break; } actualTypes[i] = currentActualTypeArgs[offset]; matched = true; break; } } } if (!matched) { //特殊: 正常情况是不可能找不到的, 会编译不通过, 这里简单的将类型赋值为Object actualTypes[i] = Object.class; } } else { //如果"当前类对于子类的泛型对象(currentGenericType)"不是ParameterizedType, 就没有办法继续查找了, 这说明子类没有确定类型, 视为Object actualTypes[i] = Object.class; } } else if (type instanceof ParameterizedType) { //可以选择转成Class if (preferRawClass) { actualTypes[i] = ((ParameterizedType) type).getRawType(); } } else if (!(type instanceof Class)){ //其他类型均视为Object.class //未实现的情况: GenericArrayType, 泛型实际类型是一个数组类型, 例如: . 这个如果要实现, 得脱壳以后, 再创建一个GenericArrayType, 得复制GenericArrayTypeImpl的源码. actualTypes[i] = Object.class; } } } return actualTypes; } /** * 指定的泛型定义类没有在父类和接口中找到. 通俗地讲, 就是遍历了类的所有父类和接口, 都没有找到匹配第二个参数targetGenericClass * 的, 所以无法获取到泛型具体类型 */ public static class TargetGenericClassNotFoundException extends Exception { private static final long serialVersionUID = 8233374476663138140L; public TargetGenericClassNotFoundException(String message) { super(message); } } // //////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Type转Class. * * @param type Type * @return Class */ public static Class typeToRawClass(Type type) { if (type == null) { return null; } // 如果是泛型数组类型(例如: T[])的话, 脱壳得到T Type componentType = type; int arrayDepth = 0; while (componentType instanceof GenericArrayType) { componentType = ((GenericArrayType) componentType).getGenericComponentType(); arrayDepth++; } // Type 转 Class Class componentClass; if (componentType instanceof Class) { componentClass = (Class) componentType; } else if (componentType instanceof ParameterizedType) { componentClass = (Class) ((ParameterizedType) componentType).getRawType(); } else { componentClass = Object.class; } // 如果不是泛型数组类型, 直接返回 if (arrayDepth <= 0) { return componentClass; } // 如果是泛型数组类型, 再转成数组类型 StringBuilder prefix = new StringBuilder("["); for (int i = 1; i < arrayDepth; i++) { prefix.append("["); } try { return Class.forName(prefix.toString() + "L" + componentClass.getName() + ";"); } catch (ClassNotFoundException e) { // 一般不会报错的, 因为componentClass存在 throw new RuntimeException("Error while creating array Class", e); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy