Getting and Setting fields
suggest changeUsing the Reflection API, it is possible to change or get the value of a field at runtime. For example, you could use it in an API to retrieve different fields based on a factor, like the OS. You can also remove modifiers like final
to allow modifing fields that are final.
To do so, you will need to use the method Class#getField() in a way such as the one shown below:
// Get the field in class SomeClass "NAME". Field nameField = SomeClass.class.getDeclaredField("NAME"); // Get the field in class Field "modifiers". Note that it does not // need to be static Field modifiersField = Field.class.getDeclaredField("modifiers"); // Allow access from anyone even if it's declared private modifiersField.setAccessible(true); // Get the modifiers on the "NAME" field as an int. int existingModifiersOnNameField = nameField.getModifiers(); // Bitwise AND NOT Modifier.FINAL (16) on the existing modifiers // Readup here https://en.wikipedia.org/wiki/Bitwise_operations_in_C // if you're unsure what bitwise operations are. int newModifiersOnNameField = existingModifiersOnNameField & ~Modifier.FINAL; // Set the value of the modifiers field under an object for non-static fields modifiersField.setInt(nameField, newModifiersOnNameField); // Set it to be accessible. This overrides normal Java // private/protected/package/etc access control checks. nameField.setAccessible(true); // Set the value of "NAME" here. Note the null argument. // Pass null when modifying static fields, as there is no instance object nameField.set(null, "Hacked by reflection..."); // Here I can directly access it. If needed, use reflection to get it. (Below) System.out.println(SomeClass.NAME);
Getting fields is much easier. We can use Field#get() and its variants to get its value:
// Get the field in class SomeClass "NAME". Field nameField = SomeClass.class.getDeclaredField("NAME"); // Set accessible for private fields nameField.setAccessible(true); // Pass null as there is no instance, remember? String name = (String) nameField.get(null);
Do note this:
When using Class#getDeclaredField, use it to get a field in the class itself:
class HackMe extends Hacked { public String iAmDeclared; } class Hacked { public String someState; }
Here, HackMe#iAmDeclared
is declared field. However, HackMe#someState
is not a declared field as it is inherited from its superclass, Hacked.
Found a mistake? Have a question or improvement idea?
Let me know.
Table Of Contents