Java反射修改static final修饰的字段

private

看一个最常见的例子

public class Pojo {
    private StringBuilder name = new StringBuilder("john");

    public void printName() {
        System.out.println(name);
    }
}

使用反射修改private修饰符的变量name

import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Pojo p = new Pojo();

        // 查看被修改之前的值
        p.printName();

        // 反射获取字段, name成员变量
        Field nameField = p.getClass().getDeclaredField("name");

        // 由于name成员变量是private, 所以需要进行访问权限设定
        nameField.setAccessible(true);

        // 使用反射进行赋值
        nameField.set(p, new StringBuilder("111"));

        // 打印查看被修改后的值
        p.printName();

    }
}

输出

john
111

static

static修饰的一个name变量

public class Pojo {
    private static StringBuilder name = new StringBuilder("john");

    public void printInfo() {
        System.out.println(name);

    }
}

使用反射修改static修饰符的变量name

import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Pojo p = new Pojo();

        // 查看被修改之前的值
        p.printInfo();

        // 反射获取字段, name成员变量
        Field nameField = p.getClass().getDeclaredField("name");

        // 进行访问权限设定
        nameField.setAccessible(true);

        // 使用反射进行赋值
        nameField.set(p,new StringBuilder("kate"));

        // 打印查看被修改后的值
        p.printInfo();

    }
}

输出

john
kate

final

刚才使用反射成功修改了private修饰的变量, 那么如果是final修饰的变量那么还能否使用反射来进行修改呢?这时候就需要分情况了。

final字段能否修改,有且取决于字段是直接赋值还是间接赋值(编译时赋值和运行时赋值的区别)。直接赋值是指在创建字段时就对字段进行赋值,并且值为JAVA的8种基础数据类型或者String类型,而且值不能是经过逻辑判断产生的,其他情况均为间接赋值。

直接赋值

定义直接赋值的final修饰符属性

public class Pojo {
    private final String name = "john";
    public final int age = 20-2;

    public void printInfo() {
        System.out.println(name+" "+age);

    }
}

尝试通过反射修改属性失败

import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Pojo p = new Pojo();

        // 查看被修改之前的值
        p.printInfo();

        // 反射获取字段, name和age成员变量
        Field nameField = p.getClass().getDeclaredField("name");
        Field ageField = p.getClass().getDeclaredField("age");

        // 进行访问权限设定
        nameField.setAccessible(true);
        ageField.setAccessible(true);

        // 使用反射进行赋值
        nameField.set(p,"kate");
        ageField.set(p,88);

        // 打印查看被修改后的值
        p.printInfo();

    }
}

输出

john 18
john 18

间接赋值

下面这些是间接赋值的final修饰符属性

public class Pojo {
    // new生成的对象赋值
    private final StringBuilder sex = new StringBuilder("male");
    // 经过逻辑判断产生的变量赋值
    public final int age = (null!=null?18:18);
    // 通过构造函数进行赋值
    private final String name;
    public Pojo(){
        name = "john";
    }
    
    public void printInfo() {
        System.out.println(name+" "+age+" "+sex);

    }
}

尝试通过反射进行修改其属性

import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Pojo p = new Pojo();

        // 查看被修改之前的值
        p.printInfo();

        // 反射获取字段, name和age和sex成员变量
        Field nameField = p.getClass().getDeclaredField("name");
        Field ageField = p.getClass().getDeclaredField("age");
        Field sexField = p.getClass().getDeclaredField("sex");

        // 进行访问权限设定
        nameField.setAccessible(true);
        ageField.setAccessible(true);
        sexField.setAccessible(true);

        // 使用反射进行赋值
        nameField.set(p,"kate");
        ageField.set(p,88);
        sexField.set(p, new StringBuilder("female"));

        // 打印查看被修改后的值
        p.printInfo();

    }
}

输出

john 18 male
kate 88 female

static + final

使用static final修饰符的name属性,并且是间接赋值

public class Pojo {
    static final StringBuilder name = new StringBuilder("john");

    public void printInfo() {
        System.out.println(name);

    }
}

通过反射去修改name属性

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Pojo p = new Pojo();

        // 查看被修改之前的值
        p.printInfo();

        // 反射获取字段, name成员变量
        Field nameField = p.getClass().getDeclaredField("name");

        // 进行访问权限设定
        nameField.setAccessible(true);

        // 再通过反射, 把nameField的final修饰符去掉
        Field modifiers = nameField.getClass().getDeclaredField("modifiers");
        modifiers.setAccessible(true);
        modifiers.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL);

        // 使用反射进行赋值
        nameField.set(p,new StringBuilder("kate"));

        // 最后别忘了再把final修饰符加回来
        modifiers.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL);

        // 打印查看被修改后的值
        p.printInfo();

    }
}

输出

john
kate

参考资料

Java反射-修改字段值, 反射修改static final修饰的字段

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇