Monday, 7 February 2011

Using java.util.Collections - 2

Yesterday’s blog, contained a quick example of using Collections.reverse(), which, from experience, is something that you don’t have to do that often; so today’s post demonstrates a more useful example. Now, one thing you often need to do is to write a method that returns a Collection (eg a List, Set, Map etc.) to its caller.


public class MyClass {

   
private List<String> myList;

 
public List<String> getMyList() {
    
return myList;
 
}
 
 
// Other code omitted for clarity
}

You may think: “what’s wrong with that?”, the answer is that you are breaking your object’s encapsulation by publishing access to its internal state. Worse than that, any client code can now modify your object’s state without accessing your object's interface. That’s bad!

The solution is simple: use Collections.unmodifiableList(..):

public class MyClass {

  
private List<String> myList;

 
public List<String> getMyList() {
   
   
return Collections.unmodifiableList(myList);
 
}

 
// Other code omitted for clarity
}

Now, if any client calls your code, and wants to add a new element to the list:
List<String> myList =  myClass.getMyList();
myList.add("Hello");
then it’ll cause a java.lang.UnsupportedOperationException and your client will know to leave your code alone. To change its copy of the list the client must do:
// Create a new modifiable copy
List copy = new LinkedList(myClass.getMyList());
copy.add("Hello");
… which means everyone’s happy: your object’s encapsulation is intact and the client’s got its own list to play with...

No comments: