{"id":604,"date":"2008-12-14T21:11:27","date_gmt":"2008-12-15T02:11:27","guid":{"rendered":"http:\/\/unitstep.net\/?p=604"},"modified":"2008-12-14T21:12:06","modified_gmt":"2008-12-15T02:12:06","slug":"handling-mutable-fields-in-java","status":"publish","type":"post","link":"https:\/\/unitstep.net\/blog\/2008\/12\/14\/handling-mutable-fields-in-java\/","title":{"rendered":"Handling mutable fields in Java"},"content":{"rendered":"
In Java, a mutable<\/em> object is one whose state can be altered after it has been instantiated. An immutable<\/em> object is one whose state is fixed after instantiation; that is, the data represented by the object cannot be changed in that object. Perhaps the most well-known immutable type is the built in String<\/a> class; while there are methods on the String class that seemingly alter its state (such as Consider the following code fragment. We create a Don’t waste too much time on this problem, as it’s a trick question. The answer actually depends on the implementation of <\/p>\n Let’s take a look at the code for We have a simple constructor that initializes the Furthermore, the original reference returned from the getter is not independent either; if some other code were to call the get method on the How can we “fix” this? We simply have to ensure that the getter for the field returns a reference to a copy<\/em> of the private Map. This is easy since there is a constructor for With these changes, the private Map cannot be altered by a caller and thus the second output will remain changed in our first code fragment example.<\/p>\n It should be noted that sometimes you may want to allow<\/em> callers to alter the backing data structure that you return from a get method. For example, some of the data structures from the Java Collection Framework<\/a> have getters that return references that can be used to alter the state of the original object. A good example is the But in my opinion, these examples are the exception rather than the rule. In general, you do not want to allow callers to be able to alter the state of private fields directly since this violates information-hiding principles. If there is some change a caller needs to make to your object, it’s best accomplished through a set method since this allows you to control the changes and prevents unwanted\/unexpected situations. If you do decide to allow callers to directly alter the state of private fields, it’s best to explicitly document this in the JavaDoc.<\/p>\n Note that in this example the field used was a toUpperCase()<\/code> and
trim()<\/code>), in actuality these methods return a new<\/em> String object if changes had to be made. In this article I’ll discuss how mutability will affect how you expose private fields in objects.<\/p>\n
Pop Quiz<\/h2>\n
MapContainer<\/code> object, and then get the contained map, which is guaranteed to have a certain value associated with the key “today”. We then alter the value associated with this key, using our local reference<\/em> to returned map. We then query the
MapContainer<\/code> object and get the contained map again. What is the value associated with the key “today” in this map?<\/p>\n
final MapContainer mapContainer = new MapContainer();\r\nfinal Map<String, String> map = mapContainer.getKeyValuePairs();\r\n\r\nfinal String today = map.get(\"today\");\r\nassert null != today;\r\nSystem.out.println(today); \/\/ Returns the current date-time.\r\n\r\n\/\/ Change the value using our local reference.\r\nmap.put(\"today\", \"tomorrow\");\r\n\r\nfinal Map<String, String> mapAgain = mapContainer.getKeyValuePairs();\r\nSystem.out.println(mapAgain.get(\"today\")); \/\/ What is output?<\/code><\/pre>\n
MapContainer<\/code>. Depending on how it’s implemented, the second output could be unchanged from the first or<\/strong> be changed to the new value of “tomorrow”.<\/p>\n
It’s all in the getters<\/h2>\n
MapContainer<\/code>. <\/p>\n
import java.util.Date;\r\nimport java.util.HashMap;\r\nimport java.util.Map;\r\n\r\npublic class MapContainer\r\n{\r\n final private Map<String, String> keyValuePairs;\r\n\r\n public MapContainer()\r\n {\r\n this.keyValuePairs = new HashMap<String, String>();\r\n this.keyValuePairs.put(\"today\", new Date().toString());\r\n }\r\n\r\n public Map<String, String> getKeyValuePairs()\r\n {\r\n return keyValuePairs;\r\n }\r\n}<\/code><\/pre>\n
keyValuePairs<\/code> Map and adds one value for the current date-time. But the real ‘key’ (no pun intended) to solving the problem is looking at the getter for the field. As you can see, it simply returns a reference to the private field. Under this implementation, a caller is able to alter the contents of the private field\/Map even though no public “set” methods are available<\/strong>. Why is this? For two reasons: In Java, objects are passed\/returned by reference, and
HashMap<\/code> is a mutable object. Thus using this implementation, the second output from our original code fragment is “tomorrow”, since the caller has altered the contents of the Map through the returned reference.<\/p>\n
MapContainer<\/code> object and make changes to the Map, those changes would also be reflected in the original returned reference!<\/p>\n
HashMap<\/code><\/a> that accepts an existing Map. Here’s the altered code:<\/p>\n
import java.util.Date;\r\nimport java.util.HashMap;\r\nimport java.util.Map;\r\n\r\npublic class MapContainer\r\n{\r\n final private Map<String, String> keyValuePairs;\r\n\r\n public MapContainer()\r\n {\r\n this.keyValuePairs = new HashMap<String, String>();\r\n this.keyValuePairs.put(\"today\", new Date().toString());\r\n }\r\n\r\n public Map<String, String> getKeyValuePairs()\r\n {\r\n return new HashMap<String, String>(keyValuePairs);<\/strong>\r\n }\r\n}<\/code><\/pre>\n
To change, or not to change?<\/h2>\n
entrySet()<\/code><\/a> method of the
HashMap<\/code> object. <\/p>\n
Mutability and safety<\/h2>\n
HashMap<\/code> object, which was mutable. If the field consisted of an immutable object, like a
String<\/code>, you would not have to worry about making a copy before returning it. This is because if the object is immutable, you do not have to worry about a caller changing its state because this is impossible to do! This is why immutable objects are much easier to deal with in multithreaded\/concurrent environments.<\/p>\n