You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Java反射修改private static final字段抛出IllegalAccessException问题

问题原因
  1. 修饰符修改逻辑代码错误
    你现有代码中尝试获取修饰符字段的逻辑有误,你调用Table.getDeclaredField(GeneratedValueFields.get(i).getName())获取到的依旧是自定义类的id字段,而非java.lang.reflect.Field类中存储字段修饰符的modifiers属性。你试图给Long类型的id字段设置int类型的修饰符值,自然会抛出类型不匹配的IllegalAccessException。
  2. static final字段的JVM特殊限制
    JVM会在类加载阶段对static final修饰的常量做内联优化,直接把常量值嵌入到所有引用该字段的代码位置,同时反射对static final字段的修改权限限制远高于实例final字段。就算正确移除final修饰符,部分JDK版本(尤其是JDK9+的模块化机制)仍然会拦截static final字段的写入操作,这也是你删除修饰符修改代码后,即使类型匹配仍然抛出访问异常的原因。
  3. 实例final字段无全局内联限制
    实例final字段不会在类加载阶段做全局内联优化,仅需移除final修饰符后就可以给对应实例的该字段赋值,不需要处理类层面的限制,因此可以正常运行。
解决办法
  • 首先修正修饰符修改代码,正确从Field类获取修饰符字段:
for (Field field : Table.getDeclaredFields()){
    System.out.println(Table.getSimpleName()); //prints "Item"
    field.setAccessible(true);
    if (field.getName().equals(GeneratedValueFields.get(i).getName())) {
        System.out.println(field.getName()); //prints "id"
        // 修正:从Field类获取modifiers字段,而非自定义的Table类
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        // 确保data是Long类型,避免类型不匹配
        Long data = Long.valueOf(9);
        field.set(null,data);
    }
}
  • 适配高版本JDK限制:如果你使用JDK9及以上版本,需要添加JVM启动参数解除模块化反射限制:--add-opens java.base/java.lang.reflect=ALL-UNNAMED
  • 优先避免修改static final字段:该操作本身稳定性极差,即使修改成功,之前已经内联了该常量的代码依旧会使用旧值,只有通过反射读取才能拿到新值,极易出现逻辑不一致。如果业务允许,优先改为实例final字段,或者去掉static修饰符。
  • 确保赋值类型匹配:如果字段类型为Long,赋值时必须传入Long类型的值,不能直接传入int类型的字面量,避免自动装箱为Integer导致类型不匹配异常。

内容的提问来源于stack exchange,提问作者Ilias Tzortzinis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 14:03:03