In JDK 1.1.x, we were not able to modify/access private fields using Reflection in Java. If someone tried to access fields which is inaccessible, the method throws an IllegalAccessException.
In JDK 1.2.x, we could make private fields accessible with setAccessible(true) method. We can even modify the final fields with Reflection.
If we set a final field of primitive type at declaration time, the value will be inlined, if the type is primitive or a String.
Lets see an example to modify final field of primitive integer type, Integer type and String type using Reflection -
import java.lang.reflect.Field;
public class ReflectionDemo {
private final String strVal1;
private final String strVal2 = "Anjan";
private final String strVal3;
private final String strVal4 = "XYZ";
private final Integer wrapperInt = 45;
private final int primInt1;
private final int primInt2 = 11;
public ReflectionDemo() {
primInt1 = 10;
strVal1 = "dummy";
strVal3 = "test";
}
public String toString() {
return "strVal1 : " + strVal1 + "; strVal2 : " + strVal2 + "; strVal3 : " + strVal3 + "; strVal4 : " + strVal4
+ "; wrapperInt : " + wrapperInt + "; primInt1 : " + primInt1
+ "; primInt2 : " + primInt2;
}
public void getMethodParameterValue(Object obj) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Class<?> cls = obj.getClass();
// Changing the value of String type which is initialized at Constructor - strVal1
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
field.set(strVal1, "new Dummy".toCharArray());
// Changing the value of String type which is declared - strVal2
field = String.class.getDeclaredField("value");
field.setAccessible(true);
field.set(strVal2, "new Anjan".toCharArray());
// Changing the value of String type which is initialized at Constructor - strVal3
field= cls.getDeclaredField("strVal3");
field.setAccessible(true);
field.set(obj, "new Test");
// Changing the value of String type which is declared - strVal4
field = cls.getDeclaredField("strVal4");
field.setAccessible(true);
field.set(obj, "new XYZ");
// Changing the value of Integer type which is declared - wrapperInt
field = Integer.class.getDeclaredField("value");
field.setAccessible(true);
field.set(wrapperInt, 30);
// Changing the value of primitive int type which is initialized at Constructor - primtInt1
field = cls.getDeclaredField("primInt1");
field.setAccessible(true);
field.set(obj, new Integer(48));
// Changing the value of primitive int type which is declared - primInt2
field = cls.getDeclaredField("primInt2");
field.setAccessible(true);
field.set(obj, new Integer(100));
}
public static void main(String args[]) throws NoSuchFieldException, IllegalAccessException {
ReflectionDemo demo = new ReflectionDemo();
System.out.println(demo);
demo.getMethodParameterValue(demo);
System.out.println(demo);
}
}
Output -
strVal1 : dummy; strVal2 : Anjan; strVal3 : test; strVal4 : XYZ; wrapperInt : 45; primInt1 : 10; primInt2 : 11
strVal1 : new Dummy; strVal2 : new Anjan; strVal3 : new Test; strVal4 : XYZ; wrapperInt : 30; primInt1 : 48; primInt2 : 11
As we discussed earlier that if we set a final field of primitive type and String at declaration time, the value will be inlined. The above highlighted field values are not changed, as strVal4 is String type and primInt2 is primitive type and we have set the values of these fields at declaration time. Hence the field value doesn't get changed.
To modify the value of final primitive type or String type we need to set the value in Constructors.
No comments:
Post a Comment