跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

反射操作List元素:动态调用get/set方法与直接Field访问对比

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

相关文章