Thursday, 13th October 2011
Follow WikiJava on twitter now. @Wikijava

Thread safe immutable class

From WikiJava

Jump to: navigation, search
The author suggests:

buy this book

There are several very complex techniques to make a class thread safe, the simplest and safest way is to make the the class immutable.

Contents

Immutable class

A class is said to be immutable if it's fields can't be modified once the object is created.

This is normally achieved by declaring the fields final. But sometimes it's not as simple as that.

A class may be partially immutable and have only some of the fields to be not modifiable. These fields must be initialized in the constructors, as they can't be changed after the creation of the object.

Immutable classes are very useful in multithread programs since they are inherently thread safe and they have no issues with synchronization. This is because once they are created they can't be changed from anyone, so you don't need to worry about it. You can just read their values any time and be sure there won't be any issue.

It is always recommended, when feasible to make your classes immutable.

Using mutable classes as immutable fields

As said sometimes having an immutable class is not so simple. For example when a final field is a not immutable class, then you can always get the value and modify it directly, this will result in changing a value what you would have considered immutable and without even notifying anyone of this change. Very dangerous.

I propose a solution for this: When you are creating the object, (since it is immutable this must be the moment when you set all the fields) you don't save the mutable objects passed to the constructor, but rather you create a copy of each one of them and keep the copy.

Similarly in the getter for these fields you don't return the object straight away, but a copy of it.

Implementing your class like this there's no way (unless using reflection) to modify the field that you want to be immutable.

I'll make this more clear in the example:

    private final Date birthday;
 
    public ImmutablePerson(String name, String surname, Date birthday) {
	super();
	this.birthday = new Date(birthday.getTime());
	this.name = name;
	this.surname = surname;
    }
 
    public Date getBirthday() {
	return new Date(this.birthday.getTime());
    }

The Date class is not immutable (I believe it should be though) to use it in an immutable class we need to make impossible to change the values of its fields. We do so as explained above. in the constructor we save a copy of the object passed and in the getter we return a copy of the object.

Immutable person

here's the complete immutable person class. note that the Birthday field uses the copy trick for granting immutabilit, while the other fields are Strings. String is (probably the most famous) immutable class, so it doesn't need to be copied each time its value is needed.

/**
 *  
 */
package org.wikijava.basic;
 
import java.util.Date;
 
/**
 * this example shows how to make an ImmutablePerson class
 * 
 * @author Giulio
 */
public class ImmutablePerson {
 
    public static void main(String[] args) {
	ImmutablePerson frank = new ImmutablePerson("frank", "lupin", new Date(
		75, 11, 23));
	System.out.println(frank.toString());
 
	// try to change the birthday of frank
	frank.getBirthday().setYear(2010);
 
	//nothing changed.
	System.out.println(frank.toString());
 
    }
 
    private final String name;
 
    private final String surname;
 
    private final Date birthday;
 
    public ImmutablePerson(String name, String surname, Date birthday) {
	super();
	this.birthday = new Date(birthday.getTime());
	this.name = name;
	this.surname = surname;
    }
 
    public Date getBirthday() {
	return new Date(birthday.getTime());
    }
 
    public String getName() {
	return name;
    }
 
    public String getSurname() {
	return surname;
    }
 
    public String toString() {
	StringBuffer result = new StringBuffer(name);
	result.append(" ").append(surname).append(" ").append(
		birthday.toString());
	return result.toString();
    }
 
}

this program gives output:

frank lupin Tue Dec 23 00:00:00 CET 1975
frank lupin Tue Dec 23 00:00:00 CET 1975

As you see the date hasn't changed after the modification.

Comments from the users

To be notified via mail on the updates of this discussion you can login and click on watch at the top of the page


Comments on wikijava are disabled now, cause excessive spam.