反射操作List元素的核心是对泛型元素对象的属性读写,分调用getter/setter方法(符合封装但性能低)和直接字段访问(性能高但绕过逻辑、有安全风险)两种方式,实际应用推荐缓存Method/Field并混合使用。
反射操作
元素时,核心不是“对 List 本身反射”,而是对 List 中的**泛型元素对象**进行属性读写。关键区别在于:是通过反射调用其 getter/setter 方法,还是绕过方法、直接访问私有字段(配合
)。两者在语义、安全性、性能和可维护性上差异明显。
调用 get/set 方法:符合封装,但开销略高
这种方式严格遵循 Java Bean 规范,通过
和
执行逻辑,能触发属性校验、日志、监听等业务逻辑(如果存在)。适合需要保留原有行为的场景,比如框架做 DTO 转换或审计增强。
必须确保目标类存在标准命名的 public 方法,否则会抛
每次调用都要解析方法签名、检查访问权限、执行栈帧压入,比直接字段访问慢约 3–5 倍(实测千万次级调用差距在百毫秒量级)
无需
,不受模块系统(Java 9+)或安全管理器限制
直接 Field 访问:快且直接,但绕过封装
使用
+
+
,跳过方法调用,直抵内存字段。性能接近原生赋值,适合高性能映射(如 JSON 反序列化库内部)。
可访问 private/protected/default 字段,但需显式设为可访问;Java 12+ 在强封装模式下可能抛
完全跳过 setter/getter 中的任何逻辑(如空值检查、格式转换、事件通知),可能引发隐性 bug
字段名硬编码,重构时易断裂;建议配合
缓存(如用
)避免重复查找
实际 List 场景中的典型写法
假设
,要批量设置每个
的
属性:
方法调用方式:
字段直写方式:
混合策略更实用:首次缓存
或
实例,后续复用;对无 setter 的字段自动降级为 field 访问
安全与兼容性提醒
在模块化环境(如 JDK 9+ 的
)中,直接访问非导出包内的私有字段会失败。此时要么开放模块导出,要么改用方法调用。生产环境若启用安全管理器,
还需授予
权限。
ListsetAccessible(true)getMethod("getXXX")invoke()NoSuchMethodExceptionsetAccessiblegetDeclaredField("xxx")setAccessible(true)set()/get()InaccessibleObjectExceptionFieldConcurrentHashMap> ListPersonnameMethod setName = Person.class.getMethod("setName", String.class); for (Person p : list) setName.invoke(p, "newName");Field nameField = Person.class.getDeclaredField("name"); nameField.setAccessible(true); for (Person p : list) nameField.set(p, "newName");MethodFieldmodule-info.javasetAccessible(true)ReflectPermission("suppressAccessChecks")