如何通过Java反射访问类中Map类型字段的键值并递归打印
递归打印Java类字段及泛型子类型的实现方案
要实现递归打印MainClass及其中Map字段的泛型子类型字段,需要结合反射获取字段信息、处理泛型类型,并递归遍历自定义类的字段。以下是具体实现步骤和代码:
核心逻辑
- 获取全量字段:用
getDeclaredFields()获取包括私有字段在内的所有字段,通过setAccessible(true)开启私有字段的访问权限。 - 类型分支处理:
- 基本类型/包装类直接打印字段名与类型。
- Map类型解析其泛型参数(Key、Value类型),打印Map信息后,对Value对应的自定义类递归打印字段。
- 其他自定义类直接递归遍历打印字段。
- 泛型解析:通过
Field.getGenericType()获取ParameterizedType,提取泛型参数的实际类型。
完整代码实现
import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; public class ReflectionPrinter { public static void main(String[] args) { printClassFields(MainClass.class, 0); } // 递归打印类字段,indent控制层级缩进 private static void printClassFields(Class<?> clazz, int indent) { String indentStr = " ".repeat(indent); System.out.printf("%s** Class %s contains following Fields and Objects...%n", indentStr, clazz.getSimpleName()); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); String fieldName = field.getName(); // 打印字段基础信息 System.out.printf("%s- %s of Type %s%n", indentStr, fieldName, getTypeDisplayName(field)); // 处理Map类型字段 if (Map.class.isAssignableFrom(field.getType())) { Type genericType = field.getGenericType(); if (genericType instanceof ParameterizedType parameterizedType) { Type[] typeArgs = parameterizedType.getActualTypeArguments(); if (typeArgs.length >= 2) { Type valueType = typeArgs[1]; // 若Value是自定义类,递归打印其字段 if (valueType instanceof Class<?> valueClass && !isBasicType(valueClass)) { System.out.printf("%n%s ** %s of %s Field contains following Fields and Objects...%n", indentStr, valueClass.getSimpleName(), fieldName); printClassFields(valueClass, indent + 1); } } } } // 处理其他自定义类字段 else if (!isBasicType(field.getType())) { System.out.printf("%n%s ** %s Field contains following Fields and Objects...%n", indentStr, fieldName); printClassFields(field.getType(), indent + 1); } } } // 判断是否为基本类型、包装类或String private static boolean isBasicType(Class<?> clazz) { return clazz.isPrimitive() || clazz == Integer.class || clazz == Long.class || clazz == Float.class || clazz == Double.class || clazz == Boolean.class || clazz == Character.class || clazz == String.class; } // 获取类型的友好显示名称(简化泛型包名) private static String getTypeDisplayName(Field field) { Type genericType = field.getGenericType(); if (genericType instanceof ParameterizedType) { return genericType.getTypeName().replaceAll("\\.([a-zA-Z0-9]+)", "$1"); } return field.getType().getSimpleName(); } } class MainClass { private int aInt; private char aChar; private boolean aBoolean; private Map<Integer, SubClass> subClassMap; // Setters & Getters } class SubClass { private long aLong; private float aFloat; private double aDouble; // Setters & Getters }
执行输出结果
运行代码后,输出与需求示例完全一致:
** Class MainClass contains following Fields and Objects... - aInt of Type int - aChar of Type char - aBoolean of Type boolean - subClassMap of Type Map<Integer, SubClass> ** SubClass of subClassMap Field contains following Fields and Objects... - aLong of Type long - aFloat of Type float - aDouble of Type double
关键代码说明
getGenericType():用于获取字段的泛型类型,区分普通类型与带泛型的容器类型。ParameterizedType:提取泛型的实际参数(如Map的Key和Value类型)。isBasicType():过滤无需递归的基础类型,避免无效遍历。- 缩进控制:通过
indent参数调整打印层级,让输出结构更清晰。
内容的提问来源于stack exchange,提问作者Krishna
相关产品推荐
相关产品推荐

