如何编写递归方法处理未知类型对象,无需使用toString()获取所有字段值
问题核心解决方法
你混淆了Field元对象和字段对应的实际实例值,要获取字段在当前被解析对象上的实际值,直接调用Field类的get()方法即可,不需要做类型转换:
// 先给Field设置可访问权限,避免私有字段抛出IllegalAccessException field.setAccessible(true); // 传入当前正在解析的外层对象o,就能拿到这个字段在o实例上存储的实际值 Object fieldValue = field.get(o); // 把实际值传入递归方法,而不是传field本身 returnString.append(field.getName()).append(":").append(" {").append(objectToString(fieldValue)).append("} ");
现有代码其他需要修复的问题
- 第一个遍历
fields的循环中边遍历边调用remove(),会导致索引偏移漏处理部分字段,建议分开两个列表存基础类型和对象类型字段,或者直接统一遍历判断类型 - 基础类型和String字段拼接时,你现有代码写的
append(fields.get(i))是打印Field元对象信息,不是字段存储的实际值,同样需要调用get(o)拿值 - 要增加空值判断,避免字段值为null时递归调用
objectToString抛空指针 - 要增加循环引用检测,比如A对象持有B、B又持有A的场景,会导致无限递归栈溢出,可以加个
Set<Object>参数记录已经处理过的对象
修复后完整可运行代码
// 对外暴露的调用方法 public String objectToString(Object o) { return objectToString(o, new HashSet<>()); } // 私有递归方法,加入已处理对象集合避免循环引用 private String objectToString(Object o, Set<Object> processed) { // 空值直接返回 if (o == null) { return "null"; } // 循环引用直接返回标记 if (processed.contains(o)) { return "[循环引用]"; } processed.add(o); // 基础类型和String直接转字符串返回 if (o.getClass().isPrimitive() || o instanceof String) { return String.valueOf(o); } StringBuilder returnString = new StringBuilder("{" + o.getClass().getName()); Field[] declaredFields = o.getClass().getDeclaredFields(); for (Field field : declaredFields) { // 绕过访问修饰符限制,可读取私有字段 field.setAccessible(true); try { Object fieldValue = field.get(o); returnString.append(", ").append(field.getName()).append(":"); if (field.getType().isPrimitive() || field.getType().equals(String.class)) { returnString.append(fieldValue); } else { // 递归处理对象类型字段 returnString.append(objectToString(fieldValue, new HashSet<>(processed))); } } catch (IllegalAccessException e) { returnString.append("[无访问权限]"); } } returnString.append("}"); return returnString.toString(); }
内容的提问来源于stack exchange,提问作者aratata
相关产品推荐
相关产品推荐

