递归获取class全字段及类型

package com.test.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;

public class ClassUtils {
    private static final Logger log = LoggerFactory.getLogger(ClassUtils.class);
    private static final Set<String> baseTypeSet = getBaseTypeSet();
    private static final Set<String> collectionTypeSet = getCollectionTypeSet();
    private static final Set<String> mapTypeSet = getMapTypeSet();

    private ClassUtils() {
    }

    @Test
    public void test1() {
        String json = JsonUtils.object2Json(ClassUtils.getFieldInfo(YourTestClass.class, new HashSet<>()));
        System.out.println(json);
        Assert.assertNotNull(json);
    }

    /**
     * <p>递归获取class全字段,以map形式返回(map的value:字段的数据类型)</p>
     *
     * <pre>
     * {
     *     "cat": {
     *         "age": "int",
     *         "name": "java.lang.String"
     *     },
     *     "catArray": [
     *         {
     *             "age": "int",
     *             "name": "java.lang.String"
     *         }
     *     ],
     *     "catList": [
     *         {
     *             "age": "int",
     *             "name": "java.lang.String"
     *         }
     *     ],
     *     "infField": "int",
     *     "intArray": [
     *         "int"
     *     ],
     *     "integerField": "java.lang.Integer",
     *     "map": {
     *         "mapKey": "java.lang.String",
     *         "mapValue": {
     *             "age": "int",
     *             "name": "java.lang.String"
     *         }
     *     },
     *     "stringArray": [
     *         "java.lang.String"
     *     ],
     *     "stringField": "java.lang.String",
     *     "stringList": [
     *         "java.lang.String"
     *     ],
     *     "stringSet": [
     *         "java.lang.String"
     *     ]
     * }
     * </pre>
     *
     * @param clazz 支持set、list、一维数组、map、基础类型、自定义类型
     * @param existClass 已存在处理过的自定义class,避免class套娃问题(如多层菜单)
     * @return
     */
    public static Map<String, Object> getFieldInfo(Class<?> clazz, Set<Class<?>> existClass) {
        HashMap<String, Object> map = new HashMap<>();
        Field[] fields = clazz.getDeclaredFields();
        map.put("oaFullPathClassName", clazz.getName());
        if (existClass.contains(clazz)) {
            map.put("duplicateClass", true);
            return map;
        }
        if (!isBaseType(clazz)) {
            existClass.add(clazz);
        }
        for (Field field : fields) {
            Class<?> type = field.getType();
            String fieldName = field.getName();
            if (isCollectionType(type)) {
                // 集合
                map.put(fieldName, getCollectionType(field, existClass));
            }else if (type.isArray()){
                // 数组,仅支持一维数组
                map.put(fieldName, getArrayType(field, existClass));
            }else if (isMapType(type)){
                // map
                map.put(fieldName, getMapType(field, existClass));
            }else {
                // 基础类型或自定义
                map.put(fieldName, getValueType(type, existClass));
            }
        }
        return map;
    }

    /**
     * 数组,仅支持一维数组
     */
    private static List<Object> getArrayType(Field field, Set<Class<?>> existClass) {
        Class<?> type = field.getType();
        String typeName = type.getTypeName();
        String[] split = typeName.split("]");
        if (split.length == 1) {
            String className = split[0].substring(0, split[0].length() - 1);
            try {
                Class<?> baseClass = CollectionUtils.getBaseClassMap().get(className);
                if (baseClass != null) {
                    // 基础类型 Class.forName获取不到
                    return getCollectionType(baseClass, existClass);
                }
                return getCollectionType(Class.forName(className), existClass);
            } catch (ClassNotFoundException e) {
                log.error("getArrayType fail.", e);
            }
            return getCollectionType(Object.class, existClass);
        }else {
            throw new ClassCastException("Unsupported type. type: " + typeName +" , fieldName:" + field.getName());
        }
    }

    private static List<Object> getCollectionType(Class<?> clazz, Set<Class<?>> existClass) {
        return Collections.singletonList(getValueType(clazz, existClass));
    }

    private static List<Object> getCollectionType(Field field, Set<Class<?>> existClass) {
        Class<?> actualTypeClazz;
        Type genericType = field.getGenericType();
        if (genericType instanceof ParameterizedType
                && ((ParameterizedType) genericType).getActualTypeArguments()[0] instanceof Class) {
            // 指定了具体泛型才能转换
            ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
            actualTypeClazz = (Class<?>) parameterizedType.getActualTypeArguments()[0];
        }else {
            actualTypeClazz = Object.class;
        }
        return getCollectionType(actualTypeClazz, existClass);
    }

    private static Map<String, Object> getMapType(Field field, Set<Class<?>> existClass) {
        HashMap<String, Object> mapTypeMap = new HashMap<>();
        Type genericType = field.getGenericType();
        if (genericType instanceof ParameterizedType
                && ((ParameterizedType) genericType).getActualTypeArguments()[0] instanceof Class
                && ((ParameterizedType) genericType).getActualTypeArguments()[1] instanceof Class) {
            // 指定了具体泛型才能转换
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            Class<?> keyClass = (Class<?>) parameterizedType.getActualTypeArguments()[0];
            mapTypeMap.put("mapKey", getValueType(keyClass, existClass));
            Class<?> valueClass = (Class<?>) parameterizedType.getActualTypeArguments()[1];
            mapTypeMap.put("mapValue", getValueType(valueClass, existClass));
        }else {
            mapTypeMap.put("mapKey", Object.class.getName());
            mapTypeMap.put("mapValue", Object.class.getName());
        }
        return mapTypeMap;
    }

    private static Object getValueType(Class<?> clazz, Set<Class<?>> existClass) {
        if (isBaseType(clazz)) {
            return clazz.getTypeName();
        }
        return getFieldInfo(clazz, existClass);
    }

    private static boolean isMapType(Class<?> clazz) {
        return mapTypeSet.contains(clazz.getName());
    }

    private static boolean isCollectionType(Class<?> clazz) {
        return collectionTypeSet.contains(clazz.getName());
    }

    private static boolean isBaseType(Class<?> clazz) {
        return baseTypeSet.contains(clazz.getName());
    }

    private static Set<String> getBaseTypeSet() {
        String[] types = {Integer.class.getName(),
                Double.class.getName(),
                Long.class.getName(),
                Short.class.getName(),
                Byte.class.getName(),
                Boolean.class.getName(),
                Character.class.getName(),
                Float.class.getName(),
                String.class.getName(),
                Object.class.getName(),
                BigDecimal.class.getName(),
                Date.class.getName(),
                int.class.getName(),
                double.class.getName(),
                long.class.getName(),
                short.class.getName(),
                byte.class.getName(),
                boolean.class.getName(),
                char.class.getName(),
                float.class.getName()};
        return new HashSet<>(Arrays.asList(types));
    }

    private static Set<String> getCollectionTypeSet() {
        String[] types = {List.class.getName(), Set.class.getName(), ArrayList.class.getName(), HashSet.class.getName()};
        return new HashSet<>(Arrays.asList(types));
    }

    private static Set<String> getMapTypeSet() {
        String[] types = {Map.class.getName(), HashMap.class.getName()};
        return new HashSet<>(Arrays.asList(types));
    }

    public static Object getFieldValue(Object obj, String fieldName) {
        for (Method method : obj.getClass().getDeclaredMethods()) {
            if (("get" + fieldName).equalsIgnoreCase(method.getName())) {
                try {
                    return method.invoke(obj);
                } catch (Exception e) {
                    log.error("getFieldValue has exception. fieldName:{}", fieldName);
                }
            }
        }
        log.warn("getFieldValue fail. fieldName:{}", fieldName);
        return null;
    }

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public class CollectionUtils {
    private static final Logger log = LoggerFactory.getLogger(CollectionUtils.class);
    private static Set<Class<?>> baseClassSet;
    private static Map<String, Class<?>> baseClassMap;

    private CollectionUtils() {
    }

    public static  <K, V> Map<K, V> collectionToMap(Collection<V> collection, Method method) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        if (collection == null || collection.isEmpty()) {
            return Collections.emptyMap();
        }
        HashMap<K, V> map = new HashMap<>();
        for (V v : collection) {
            map.put((K)method.invoke(v), v);
        }
        return map;
    }

    public static Map<String, Class<?>> getBaseClassMap() {
        if (baseClassMap == null) {
            try {
                Method method = Class.class.getDeclaredMethod("getName");
                baseClassMap = collectionToMap(getBaseClassSet(), method);
            } catch (Exception e) {
                log.error("getBaseTypeMap fail", e);
                baseClassMap = Collections.emptyMap();
            }
        }
        return baseClassMap;
    }

    public static Set<Class<?>> getBaseClassSet() {
        if (baseClassSet == null) {
            Class<?>[] clazzArray = {int.class,
                    double.class,
                    long.class,
                    short.class,
                    byte.class,
                    boolean.class,
                    char.class,
                    float.class};
            baseClassSet = new HashSet<>(Arrays.asList(clazzArray));
        }
        return baseClassSet;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值