Popular Posts

Sunday, January 08, 2006

Immutable object in java

Immutable objects are simply objects whose state (the object's data) does not change after construction.
Immutable objects greatly simplify your program, since they
are simple to construct, test, and use
are automatically thread-safe and have no synchronization issues
do not need a copy constructor
do not need an implementation of clone
do not need to be copied defensively when used as a field
make good Map keys and Set elements (these objects must not change state while in the collection)
the class invariant is established once upon construction, and never needs to be checked again Make a class immutable by following these guidelines :
always construct an object completely, instead of using a no-argument constructor combined with subsequent calls to setXXX methods
do not provide any methods which can change the state of the object in any way - not just setXXX methods, but any method which can change state
ensure no methods can be overridden - make the class final, or use static factories and keep constructors private
make fields final
if the state of a mutable object field is "owned" by the native class, and the intention is to allow direct access to the field only from within that native class, then, when the field "crosses the interface" (as in a get or set method, or in the constructor itself), then a defensive copy must be made, in order to maintain encapsulation.
if the state of a mutable object field is not "owned" by the native class, then a defensive copy of the object field is not necessary In Effective Java, Joshua Bloch makes this recommendation:
"Classes should be immutable unless there's a very good reason to make them mutable....If a class cannot be made immutable, you should still limit its mutability as much as possible."
Example import java.util.Date;
/**
* Planet is an immutable class, since there is no way to change
* its state after construction.
*
* @is.Immutable
*/
public final class Planet {
public Planet (double aMass, String aName, Date aDateOfDiscovery) {
fMass = aMass;
fName = aName;
//make a private copy of aDateOfDiscovery
//this is the only way to keep the fDateOfDiscovery
//field private, and shields this class from any changes
//to the original aDateOfDiscovery object
fDateOfDiscovery = new Date(aDateOfDiscovery.getTime());
}
//gets but no sets, and no methods which change state
public double getMass() {
return fMass;
}
public String getName() {
return fName;
}
/**
* Returns a defensive copy of the field.
* The caller of this method can do anything they want with the
* returned Date object, without affecting the internals of this
* class in any way.
*/
public Date getDateOfDiscovery() {
return new Date(fDateOfDiscovery.getTime());
}
// PRIVATE //
/**
* Primitive data is always immutable.
*/
private final double fMass;
/**
* An immutable object field. (String objects never change state.)
*/
private final String fName;
/**
* A mutable object field. In this case, the state of this mutable field
* is to be changed only by this class. (In other cases, it makes perfect
* sense to allow the state of a field to be changed outside the native
* class; this is the case when a field acts as a "pointer" to an object
* created elsewhere.)
*/
private final Date fDateOfDiscovery;
}

Note that javadoc 1.4 includes the -tag option, whereby simple custom tags may be defined. One might define an @is.Immutable tag, for example, to document a class as being immutable.

cheers!
Rudra

1 comment:

Rahul Mehrotra said...

Nice info rudra!
do u have sthing at collections classes also?