0

0

使用反射在 Java 17 中修改 final 字段

花韻仙語

花韻仙語

发布时间:2025-08-15 19:54:00

|

1980人浏览过

|

来源于php中文网

原创

使用反射在 java 17 中修改 final 字段

本文介绍了在 Java 17 中通过反射修改非静态 final 字段的方法。由于 Java 版本更新带来的限制,传统的修改 modifiers 字段的方式已不再适用。本文将提供一种基于 VarHandle 的解决方案,并详细说明了所需的 JVM 启动参数和代码实现,帮助开发者在必要时突破 final 限制。

Java 17 及更高版本修改 Final 字段的新方法

在 Java 12 及其之后的版本中,直接通过反射修改 Field 对象的 modifiers 字段来移除 FINAL 修饰符的方式已经失效。这是由于 Java 模块化的引入以及对反射访问的更严格限制所致。 然而,我们仍然可以通过 VarHandle 类来达到修改 final 字段的目的。

解决方案:使用 VarHandle

VarHandle 是 Java 9 引入的一个强大的 API,它提供了一种更加灵活和安全的访问变量的方式,包括可以通过反射访问私有字段。以下是在 Java 17 中修改 final 字段的步骤:

  1. 添加 JVM 启动参数:

    立即学习Java免费学习笔记(深入)”;

    由于模块化的限制,我们需要通过 JVM 启动参数来允许反射访问 java.lang.reflect.Field 类的内部成员。添加以下参数到 JVM 启动配置中:

    XPaper Ai
    XPaper Ai

    AI撰写论文、开题报告生成、AI论文生成器尽在XPaper Ai论文写作辅助指导平台

    下载
    --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
    --add-opens=java.base/java.net=ALL-UNNAMED

    这些参数允许所有未命名的模块(例如,你的应用程序代码)访问 java.lang.reflect 包和 java.net 包的内部成员。 如果没有这些参数,将会抛出java.lang.IllegalAccessException异常。

  2. 使用 VarHandle 修改 modifiers 字段:

    以下代码演示了如何使用 VarHandle 来修改 final 字段:

    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;
    import java.lang.invoke.MethodHandles;
    import java.lang.invoke.VarHandle;
    
    class Foo {
        private final String bar;
    
        public Foo(String bar) {
            this.bar = bar;
        }
    
        public String getBar() {
            return this.bar;
        }
    }
    
    public class Example {
    
        public static void main(String[] args) throws Throwable {
            Foo foo = new Foo("foobar");
            System.out.println(foo.getBar());
    
            try {
                Field field = foo.getClass().getDeclaredField("bar");
                field.setAccessible(true);
    
                VarHandle MODIFIERS;
                var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
                MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class);
                MODIFIERS.set(field, field.getModifiers() & ~Modifier.FINAL);
    
                field.set(foo, "new value"); // 设置新的值
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            System.out.println(foo.getBar());
        }
    }

    代码解释:

    • MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup()): 创建一个用于在 Field 类中进行私有查找的 MethodHandles.Lookup 对象。
    • lookup.findVarHandle(Field.class, "modifiers", int.class): 在 Field 类中查找名为 "modifiers" 的 int 类型的 VarHandle。
    • MODIFIERS.set(field, field.getModifiers() & ~Modifier.FINAL): 使用 VarHandle 将 field 对象的 modifiers 字段的值更新为原始值与 ~Modifier.FINAL 进行按位与运算的结果,从而移除 FINAL 修饰符。
    • field.set(foo, "new value");: 设置字段的新值。

注意事项

  • 安全性: 通过反射修改 final 字段可能会破坏对象的内部状态,因此应谨慎使用。 确保你完全理解代码的含义,并且只在必要时才使用这种方法。
  • 兼容性: 虽然这种方法在 Java 17 中有效,但未来的 Java 版本可能会引入新的限制,导致代码失效。
  • 静态 Final 字段: 请注意,修改 static final 字段通常是不可能的,因为这些字段的值在类加载时就已经确定,并且存储在常量池中。

总结

虽然 Java 对反射访问的限制越来越严格,但我们仍然可以通过 VarHandle 等 API 来实现一些高级功能,例如修改 final 字段。 然而,务必谨慎使用这些技术,并充分了解其潜在的风险和限制。 始终建议优先考虑使用更安全和更可靠的替代方案。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1501

2023.10.24

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

463

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

544

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

93

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

200

2025.08.29

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

469

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

13

2025.12.06

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

2

2026.01.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

446

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
SQL 教程
SQL 教程

共61课时 | 3.6万人学习

10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号