Java Language Misuse of Reflection API to change private and final variables


Example

Reflection is useful when it is properly used for right purpose. By using reflection, you can access private variables and re-initialize final variables.

Below is the code snippet, which is not recommended.

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++;
    }
}

Output:

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

Explanation:

In normal scenario, private variables can't be accessed outside of declared class ( without getter and setter methods). final variables can't be re-assigned after initialization.

Reflection breaks both barriers can be abused to change both private and final variables as explained above.

field.setAccessible(true) is the key to achieve desired functionality.