java 反射处理final修饰符

本文探讨了如何使用Java反射修改final修饰的属性值,以及尝试动态添加final修饰符。虽然可以反射修改final属性,但动态添加final后,直接赋值不生效,仅反射修改时受限。文中通过测试案例展示了静态与动态更改final属性值的不同行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们指定java 使用final修饰符修饰的属性的值不能修改或其引用的地址不可修改,那么使用反射能否进行修改呢?答案是肯定的,但是却并没有那么简单. 笔者还想尝试为属性动态添加final 修饰符, 以实现类似只读变量,但是由于java对静态变量的编译机制问题,并不能实现.

1. 反射工具类

笔者开发一个简答的ReflectUtil, 实现为属性新增或删除final 修饰符

/**
 * 反射工具类
 */
public class ReflectUtil {


    /**
     * 设置field的final修饰符
     * @param field
     * @param isFinal 是否使用final 修饰
     * @auth zongf
     * @date 2019-05-13
     */
    public static void setModifierFinal(Field field, boolean isFinal) {

        int modifiers = field.getModifiers();

        try {
            if (isFinal) {
                // 设置为final

                if (!Modifier.isFinal(modifiers)) {
                    Field aClass = field.getClass().getDeclaredField("modifiers");
                    aClass.setAccessible(true);
                    aClass.setInt(field, field.getModifiers() | Modifier.FINAL);
                    aClass.setAccessible(false);
                }
            }else {
                // 接触final
                if (Modifier.isFinal(modifiers)) {
                    Field aClass = field.getClass().getDeclaredField("modifiers");
                    aClass.setAccessible(true);
                    aClass.setInt(field, field.getModifiers() & ~Modifier.FINAL);
                    aClass.setAccessible(false);
                }
            }

            System.out.println("isFinal:" + Modifier.isFinal(field.getModifiers()));
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

}

2. 静态常量类

定义静态常量类,用于测试.定义两个静态属性, 一个使用final 修饰, 一个不使用final 修饰。

public class ProxyConstant {

    public static final String host = "127.0.0.1";

    public static String port = "8080";
}

3. 测试-反射修改final属性的值

@Test
public void test() throws NoSuchFieldException, IllegalAccessException {

    System.out.println("原: host=" + ProxyConstant.host);

    Class clz = ProxyConstant.class;

    Field host = clz.getDeclaredField("host");

    ReflectUtil.setModifierFinal(host, false);

    host.set(null, "localhost");

    System.out.println("新: host=" + ProxyConstant.host);
}

4. 测试-反射添加final 修饰符

笔者想动态为属性添加final修饰符,然后实现属性只读功能。但是发现动态添加final修饰符后,只有在反射修改时才能限制住,直接正向赋值并不生效。大概应该时静态变量的赋值在编译时有特殊处理吧, 特此记录一下.

4.1 静态更改值

动态设置属性为final之后, 静态设置值不会报错,且会修改成功。这个大概是静态变量的编译有所区别吧

@Test
public void test2() throws NoSuchFieldException, IllegalAccessException {

    System.out.println("原: port=" + ProxyConstant.port);

    Class clz = ProxyConstant.class;

    Field port = clz.getDeclaredField("port");

    ReflectUtil.setModifierFinal(port, true);

    // 静态设置时不会报错
    ProxyConstant.port = "80";

    System.out.println("新: port=" + ProxyConstant.port);

}

4.2 动态更改值

动态设置属性为final之后, 动态设置值会报错,不能修改

@Test(expected = java.lang.IllegalAccessException.class)
public void test3() throws NoSuchFieldException, IllegalAccessException {

    System.out.println("原: port=" + ProxyConstant.port);

    Class clz = ProxyConstant.class;

    Field port = clz.getDeclaredField("port");

    ReflectUtil.setModifierFinal(port, true);

    // 动态设置值时会报错
    port.set(null,"80");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值