I've created this code to show the unexpected behavior:
package reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
public class App {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person();
System.out.println("Fields of person object: ");
Arrays.stream(person.getClass().getDeclaredFields()).forEach(System.out::println);
final Field finalField = person.getClass().getDeclaredField("finalName");
final Field blankFinalField = person.getClass().getDeclaredField("blankFinalName");
System.out.println("\nOriginal modifiers and accessibility: ");
printAccessibilityAndModifiers(person, finalField);
printAccessibilityAndModifiers(person, blankFinalField);
// Changes the access to reflected object to accesible.
// You can see that it doesn't change modifiers.
finalField.setAccessible(true);
blankFinalField.setAccessible(true);
System.out.println("\nAfter set accessible to true: " + person);
printAccessibilityAndModifiers(person, finalField);
printAccessibilityAndModifiers(person, blankFinalField);
// Removing final modifier.
removeModifier(finalField, Modifier.FINAL);
removeModifier(blankFinalField, Modifier.FINAL);
System.out.println("\nAfter remove final modifier: " + person);
printAccessibilityAndModifiers(person, finalField);
printAccessibilityAndModifiers(person, blankFinalField);
finalField.set(person, "Dilson");
blankFinalField.set(person, "Dilson");
System.out.println("\nAfter change the value of field: " + person);
printAccessibilityAndModifiers(person, finalField);
printAccessibilityAndModifiers(person, blankFinalField);
// For final field, even removing final modifier, the field keeps unchanged.
System.out.println("\nThe value returned by getter of the instance: " + person);
System.out.println(finalField.getName() + ": " + person.getFinalName());
System.out.println(blankFinalField.getName() + ": " + person.getBlankFinalName());
}
private static void printAccessibilityAndModifiers(Object instance, Field field) {
System.out.println(field.getName()
+ " - Value: " + getValue(instance, field)
+ " - Is Accessible: " + field.canAccess(instance)
+ " - Modifiers: " + Modifier.toString(field.getModifiers()));
}
private static Object getValue(Object instance, Field field) {
try {
return field.get(instance);
} catch (IllegalAccessException e) {
return "Can't access " + field.getName() + " value.";
}
}
private static void removeModifier(Field field, int modifier) throws NoSuchFieldException, IllegalAccessException {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~modifier);
}
}
import lombok.Data;
@Data
public class Person {
private final String finalName = "Leandro";
private final String blankFinalName;
public Person() {
blankFinalName = "Leandro";
}
}
I would like to understand deeply what makes Java behaves differently in these situations.
Aucun commentaire:
Enregistrer un commentaire