Last active
December 10, 2015 23:28
-
-
Save szarnekow/4509688 to your computer and use it in GitHub Desktop.
Modify final fields
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Doh { | |
public static void main(String[] args) throws Exception { | |
Person p = new Person("Name"); | |
setName(p, "New Name"); | |
setDefault("Bob"); | |
System.out.println(p.getName()); | |
System.out.println(Person.DEFAULT); | |
} | |
/** | |
* Allows to change the state of an immutable instance. Huh?!? | |
*/ | |
private static void setName(Person p, String newName) throws Exception { | |
Field nameField = p.getClass().getDeclaredField("name"); | |
setValue(p, nameField, newName); | |
} | |
/** | |
* Allows to change the state of final statics. Huh?!? | |
*/ | |
private static void setDefault(String newDefault) throws Exception { | |
Field staticField = Person.class.getDeclaredField("DEFAULT"); | |
setValue(null, staticField, newDefault); | |
} | |
/** | |
* | |
* Set the value of a field reflectively. | |
*/ | |
protected static void setValue(Object owner, Field field, Object value) throws Exception { | |
makeModifiable(field); | |
field.set(owner, value); | |
} | |
/** | |
* | |
* Force the field to be modifiable and accessible. | |
*/ | |
protected static void makeModifiable(Field nameField) throws Exception { | |
nameField.setAccessible(true); | |
int modifiers = nameField.getModifiers(); | |
Field modifierField = nameField.getClass().getDeclaredField("modifiers"); | |
modifiers = modifiers & ~Modifier.FINAL; | |
modifierField.setAccessible(true); | |
modifierField.setInt(nameField, modifiers); | |
} | |
} | |
/** | |
* An immutable data class. | |
*/ | |
class Person { | |
// avoid inlining by calling newString("unnamed") | |
public static final String DEFAULT = new String("unnamed"); | |
private final String name; | |
public Person(String name) { | |
this.name = name == null ? DEFAULT : name; | |
} | |
public String getName() { | |
return name; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Force the field to be modifiable and accessible. | |
*/ | |
protected static void makeModifiable(Field nameField) throws Exception { | |
nameField.setAccessible(true); | |
int modifiers = nameField.getModifiers(); | |
Field modifierField = nameField.getClass().getDeclaredField("modifiers"); | |
modifiers = modifiers & ~Modifier.FINAL; | |
modifierField.setAccessible(true); | |
modifierField.setInt(nameField, modifiers); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Force the field to accessible. | |
*/ | |
protected static void makeModifiable(Field nameField) throws Exception { | |
nameField.setAccessible(true); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* An immutable data class. | |
*/ | |
class Person { | |
private final String name; | |
public Person(String name) { | |
this.name = name; | |
} | |
public String getName() { | |
return name; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment