濫用 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) 是實現所需功能的關鍵。