Friday, June 26, 2015

Immutable vs Unmodifiable

Immutable is one of the most important programming language concepts. Immutable is an read-only object which can not be changed, if there is any changes, a new copy will be created with updated version. internally the object state can be altered but the changes won't be reflected from the outside.

Most of immutable are value object to represent a certain business domain. Unmodifiable, is "read-only view" of the object. Similar to immutable it can not be changed from outside, but internally the object state can be altered and the changes can be reflected on the view.

In the Java Collection tutorial, one of the way to create immutable object is to construct one without reference to it, so it can't be changed.

In classic "effective java" book, it presents 5 rules to create immutable class:
1. don't provide methods to change object state. This is how JDK's Collections.unmodifiable does.
2. all fields are final
3. all fields are private
4. class can't be subclassed, either by declared it final or don't provide public/protected constructor.
5. exclusive access to object mutable state.

Immutable is particularly useful in concurrent programming since it is thread-safe. In Java and many other languages as well, String, Float, Double and Integer are immutable.

Here are two unit test cases to demonstrate the immutable and unmodifiable.


@Test
public void unmodifiableTest(){
List<String> modifiable = new ArrayList<String>();
modifiable.add("1");
List<String> unmodifiable = Collections.unmodifiableList(modifiable);
assertTrue("should have the same size", modifiable.size() == unmodifiable.size());
modifiable.add("2");
assertTrue("should still have the same size", modifiable.size() == unmodifiable.size());
try{
unmodifiable.add("3");
assertTrue("should not succeed", false);
}catch(UnsupportedOperationException ex){
assertTrue("should throw exception", true);
}
assertTrue("should still have the same size", modifiable.size() == unmodifiable.size());
}

@Test
public void immutableTest(){
List<String> modifiable = new ArrayList<String>();
modifiable.add("1");
List<String> immutable = Collections.unmodifiableList(new ArrayList<String>(modifiable));
assertTrue("should have the same size", modifiable.size() == immutable.size());
modifiable.add("2");
assertTrue("should no longer have the same size", modifiable.size() != immutable.size());
try{
immutable.add("3");
assertTrue("should not succeed", false);
}catch(UnsupportedOperationException ex){
assertTrue("should throw exception", true);
}
}

1 comment: