Java获取对象及内部对象变量名、自定义列表类名与对象的实现方法
看来你需要的是一套能深度遍历对象结构的反射工具——不仅要获取当前对象的表层字段,还要能钻取嵌套对象、解析集合里的元素信息,这在做调试、日志打印或者对象序列化工具时特别实用。下面针对你的需求给出完整解决方案:
解决方案:深度递归的对象信息获取工具
首先得指出你原有代码的两个核心局限:
- 只能获取公共(public)字段,私有/保护字段会被忽略
- 没有处理嵌套对象和集合类型,无法深度遍历对象结构
我们可以通过递归反射+类型分支处理来实现任意对象的全量信息获取,下面是具体实现:
核心实现思路
- 递归遍历对象的所有字段(包括私有字段)
- 根据字段值的类型做分支处理:
- 基本类型/包装类/字符串:直接输出字段名、类型和值
- 嵌套对象:递归调用获取其内部所有字段信息
- 集合/数组:遍历每个元素,输出元素的类名和详细信息
- 加入循环引用防护,避免无限递归
完整代码实现
import java.lang.reflect.Field; import java.lang.reflect.Array; import java.util.*; public class ObjectInspector { // 记录已处理的对象,防止循环引用导致无限递归 private static final Set<Object> processedObjects = new HashSet<>(); public static void inspectObject(Object obj) { if (obj == null || processedObjects.contains(obj)) { System.out.println(obj); return; } processedObjects.add(obj); Class<?> clazz = obj.getClass(); System.out.printf("=== 类名: %s ===%n", clazz.getSimpleName()); // 获取类的所有字段(包括私有、保护字段) Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); // 突破访问限制,允许访问私有字段 try { Object fieldValue = field.get(obj); System.out.printf("字段名: %s, 类型: %s, 值: ", field.getName(), field.getType().getSimpleName()); // 根据字段值类型分情况处理 if (isBasicType(fieldValue)) { System.out.println(fieldValue); } else if (fieldValue instanceof Collection) { inspectCollection((Collection<?>) fieldValue); } else if (fieldValue.getClass().isArray()) { inspectArray(fieldValue); } else { // 嵌套对象,递归处理其内部结构 System.out.println(); inspectObject(fieldValue); } } catch (IllegalAccessException e) { System.out.println("无法访问字段: " + e.getMessage()); } } processedObjects.remove(obj); // 处理完当前对象后移除,不影响其他分支遍历 } // 判断是否为基本类型、包装类或字符串 private static boolean isBasicType(Object obj) { if (obj == null) return true; Class<?> clazz = obj.getClass(); return clazz.isPrimitive() || clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Boolean.class) || clazz.equals(Character.class) || clazz.equals(Byte.class) || clazz.equals(Short.class); } // 处理集合类型(List/Set等) private static void inspectCollection(Collection<?> collection) { System.out.printf("集合类型: %s, 元素数量: %d%n", collection.getClass().getSimpleName(), collection.size()); int index = 0; for (Object element : collection) { System.out.printf(" 元素[%d] - 类名: %s, 值: ", index, element != null ? element.getClass().getSimpleName() : "null"); if (isBasicType(element)) { System.out.println(element); } else { System.out.println(); inspectObject(element); } index++; } } // 处理数组类型 private static void inspectArray(Object array) { int length = Array.getLength(array); System.out.printf("数组类型: %s, 长度: %d%n", array.getClass().getComponentType().getSimpleName(), length); for (int i = 0; i < length; i++) { Object element = Array.get(array, i); System.out.printf(" 元素[%d] - 类名: %s, 值: ", i, element != null ? element.getClass().getSimpleName() : "null"); if (isBasicType(element)) { System.out.println(element); } else { System.out.println(); inspectObject(element); } } } // 测试用例(对应你给出的A、B类) static class A { String a = "nil"; B b = new B(); List<B> bList = Arrays.asList(new B(), new B()); } static class B { int n1 = 0; String n2 = "testB"; } public static void main(String[] args) { inspectObject(new A()); } }
关键功能说明
- 获取嵌套对象详情:比如你的
A类里的b对象,代码会自动递归调用inspectObject,输出B类的所有字段(包括私有字段) - 获取自定义列表信息:
inspectCollection方法会输出集合的类名(比如ArrayList)、元素数量,还会逐个遍历元素,输出每个元素的类名和详细信息 - 兼容多种类型:支持基本类型、包装类、字符串、集合、数组、嵌套对象的全量遍历
- 防循环引用:用
processedObjects集合记录已处理的对象,避免对象互相引用导致的无限递归
测试输出示例
运行main方法后,会输出类似以下的结构化结果:
=== 类名: A === 字段名: a, 类型: String, 值: nil 字段名: b, 类型: B, 值: === 类名: B === 字段名: n1, 类型: int, 值: 0 字段名: n2, 类型: String, 值: testB 字段名: bList, 类型: List, 值: 集合类型: ArrayList, 元素数量: 2 元素[0] - 类名: B, 值: === 类名: B === 字段名: n1, 类型: int, 值: 0 字段名: n2, 类型: String, 值: testB 元素[1] - 类名: B, 值: === 类名: B === 字段名: n1, 类型: int, 值: 0 字段名: n2, 类型: String, 值: testB
内容的提问来源于stack exchange,提问作者Midhilaj
相关产品推荐
相关产品推荐

