Java通过反射访问及修改类内的私有变量

  写mod的时候,界面某项功能显示定位需要用到玩家周围的boss信息,然而这个信息存储在一个私有的Map变量里,所在的类也没有提供get方法。最后发现可以利用反射获取该私有变量的值。

以下是示例代码,其中field.setAccessible(true)最为重要。

import java.util.ArrayList;
import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
        TestClass testClass = new TestClass();
        // 获取TestClass对象的所有变量
        Field[] fields = testClass.getClass().getDeclaredFields();
        for (Field field : fields){
            // 设置为为true时可访问私有类型变量
            field.setAccessible(true);
            // 根据获取到的变量名输出变量值
            // 这里的get和set可能抛出IllegalAccessException异常
            switch(field.getName()){
                case "integer":
                    System.out.println("integer:" + field.get(testClass));
                    break;
                case "string":
                    // 即使是final修饰的变量也能改变其值
                    field.set(testClass, "new text");
                    System.out.println("string:" + field.get(testClass));
                    break;
                case "arrayList":
                    @SuppressWarnings("unchecked")
                    ArrayList<Double> arrayList = (ArrayList<Double>) field.get(testClass);
                    arrayList.add(5.6);
                    for(Double d : arrayList){
                        System.out.println("arrayList:" + d);
                    }
            }
        }
        // 也可以根据已知的变量名获取值,但是可能抛出NoSuchFieldException异常
        Field field = testClass.getClass().getDeclaredField("integer");
        field.setAccessible(true);
        field.set(testClass, 1);
        System.out.println("integer:" + field.get(testClass));
    }
}

class TestClass{
    public final int integer = 0;
    private final String string = "text";
    private final ArrayList<Double> arrayList = new ArrayList<>();

    public TestClass(){
        arrayList.add(1.2);
        arrayList.add(3.4);
    }
}

 

posted @ 2020-08-02 18:45  星辰°  阅读(2114)  评论(0编辑  收藏  举报