滥用 Reflection API 来更改私有变量和最终变量

当正确使用反射时,反射非常有用。通过使用反射,你可以访问私有变量并重新初始化最终变量。

以下是代码段,推荐使用。

import java.lang.reflect.*;

public class ReflectionDemo{
    public static void main(String args[]){
        try{
            Field[] fields = A.class.getDeclaredFields();
            A a = new A();
            for ( Field field:fields ) {
                if(field.getName().equalsIgnoreCase("name")){
                    field.setAccessible(true);
                    field.set(a, "StackOverFlow");
                    System.out.println("A.name="+field.get(a));
                }
                if(field.getName().equalsIgnoreCase("age")){
                    field.set(a, 20);
                    System.out.println("A.age="+field.get(a));
                }
                if(field.getName().equalsIgnoreCase("rep")){
                    field.setAccessible(true);
                    field.set(a,"New Reputation");
                    System.out.println("A.rep="+field.get(a));
                }
                if(field.getName().equalsIgnoreCase("count")){
                    field.set(a,25);
                    System.out.println("A.count="+field.get(a));
                }
            }                
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

class A {
    private String name;
    public int age;
    public final String rep;
    public static int count=0;
    
    public A(){
        name = "Unset";
        age = 0;
        rep = "Reputation";
        count++;
    }
}

输出:

A.name=StackOverFlow
A.age=20
A.rep=New Reputation
A.count=25

说明:

在正常情况下,private 变量不能在声明的类之外访问(没有 getter 和 setter 方法)。初始化后无法重新分配 final 变量。

Reflection 打破两个障碍可以被滥用来改变私人和最终变量,如上所述。

field.setAccessible(true) 是实现所需功能的关键。