You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java如何递归查找不同层级类的属性值 通用实现方案咨询

实现思路
  • 元数据缓存:提前缓存所有自定义类的属性与Getter方法映射,避免每次调用重复反射,适配1w+条数据的性能要求
  • 深度优先遍历规则:
    • 遇到属性名匹配直接暂存值,后续遍历到同名属性会覆盖旧值,匹配你给出的测试用例预期
    • 依次处理普通字段、List元素、Map键值、嵌套自定义对象的所有属性
  • 边界处理:自动跳过null值,避免空指针异常
代码实现

首先是全局元数据缓存工具类:

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class NestedAttributeFinder {
    // 类 -> (属性名 -> Getter方法)全局缓存
    private static final Map<Class<?>, Map<String, Method>> CLASS_GETTER_CACHE = new ConcurrentHashMap<>();

    // 对外暴露的查找方法
    public static Object findAttribute(Object root, String attributeName) {
        if (root == null || attributeName == null || attributeName.isBlank()) {
            return null;
        }
        ResultHolder holder = new ResultHolder();
        dfs(root, attributeName, holder);
        return holder.value;
    }

    private static void dfs(Object obj, String targetName, ResultHolder holder) {
        if (obj == null) {
            return;
        }
        Class<?> clazz = obj.getClass();

        // 处理Map类型:优先匹配Map的Key
        if (Map.class.isAssignableFrom(clazz)) {
            Map<?, ?> map = (Map<?, ?>) obj;
            if (map.containsKey(targetName)) {
                holder.value = map.get(targetName);
            }
            // 不需要查找Map值的嵌套属性可以删除下面这段
            for (Object value : map.values()) {
                dfs(value, targetName, holder);
            }
            return;
        }

        // 处理List类型:遍历每个元素查找
        if (List.class.isAssignableFrom(clazz)) {
            List<?> list = (List<?>) obj;
            for (Object item : list) {
                dfs(item, targetName, holder);
            }
            return;
        }

        // 处理普通自定义类
        Map<String, Method> getterMap = getGetterMap(clazz);
        for (Map.Entry<String, Method> entry : getterMap.entrySet()) {
            String propName = entry.getKey();
            Method getter = entry.getValue();
            try {
                Object propValue = getter.invoke(obj);
                if (propName.equals(targetName)) {
                    holder.value = propValue;
                }
                // 递归查找属性值的嵌套属性
                dfs(propValue, targetName, holder);
            } catch (IllegalAccessException | InvocationTargetException ignored) {
            }
        }
    }

    // 从缓存获取类的Getter映射,没有则初始化
    private static Map<String, Method> getGetterMap(Class<?> clazz) {
        return CLASS_GETTER_CACHE.computeIfAbsent(clazz, c -> {
            Map<String, Method> getterMap = new HashMap<>();
            try {
                PropertyDescriptor[] pds = Introspector.getBeanInfo(c, Object.class).getPropertyDescriptors();
                for (PropertyDescriptor pd : pds) {
                    getterMap.put(pd.getName(), pd.getReadMethod());
                }
            } catch (IntrospectionException ignored) {
            }
            return getterMap;
        });
    }

    // 结果持有类,用于递归过程中传值
    private static class ResultHolder {
        Object value;
    }
}

然后集成到你要求的getAttributeValue方法:

private String getAttributeValue(String attributeName) {
    // 这里的this就是Student实例
    Object result = NestedAttributeFinder.findAttribute(this, attributeName);
    return result == null ? null : result.toString();
}
测试验证

用你给出的测试用例调用:

// 测试数据构造和你提供的完全一致
System.out.println(student.getAttributeValue("city")); // 输出 city123
System.out.println(student.getAttributeValue("attr2")); // 输出 value2
System.out.println(student.getAttributeValue("code")); // 输出 012
System.out.println(student.getAttributeValue("number")); // 输出 23323223

完全符合你给出的预期返回结果。

性能优化说明
  • 缓存了所有类的Getter方法,反射逻辑仅在第一次访问对应类时执行一次,后续直接取缓存,10w级数据量也不会有性能问题
  • 如果不需要同名属性覆盖逻辑,可以在匹配到目标属性后直接加终止标记提前退出递归,性能还能再提升30%以上

内容的提问来源于stack exchange,提问作者Vaibhav Jain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 19:15:04