Home > Best Practices, Learn This, Opinion > Learn This: When and how to make Immutable objects

Learn This: When and how to make Immutable objects

February 24th, 2009

It can be sometimes difficult to see why someone would want to create an immutable class. We as programmers LOVE to be in control of things, which is what immutable classes limit us to. So what is an immutable class? An immutable class is a object who can not change once it is initialized. All values of that object are fixed and will not change throughout the lifetime of that object. While it may sound like something we dont want, in this article, I will discuss how to make an object immutable and I will also talk about when to use and not use them.

How to make an object immutable

When asked how to make an object immutable, first thing on everyone might say is ‘remove set functions’. That would be right. However, there are a set of rules that we must follow. Here they are.

  • Do not provide any methods such as setters or any methods that may alter the properties of that object. If you do, make sure they return a new instance of your object.
  • All properties and methods of that object are to be marked as final. Marking the methods as final is extremely important. We don’t want anyone carelessly overridding our functions that may compromise our immutable behavior.
  • All properties of that object are to be marked as private.

Looking at these rules may not be the best way to convey the message of why we want our objects immutable, so let’s take a look at an example.

Example of an immutable object

The simplest example I can think of where an immutable class make the most sense is within a historical data point for something like a chart or graph. There is no reason historical data needs to change throughout the lifetime of that object. It’s in the past for christ sake :) . So lets take a look an object that holds a departments budget for the year.

public final class DepartmentBudgetData {
    private float _budget;
    private String _name;
    private Date _date;
 
    public DepartmentBudgetData(float budget, String name, Date date){
        _budget = budget;
        _name = name;
        _date = date;
    }
 
    public final float getBudget() {
        return _budget;
    }
 
    public final String getName() {
        return _name;
    }
 
    public final Date getDate() {
        //returning a new Date requires the use of defensive copying.   
        return new Date(_date.getTime());
    }
}

Here is a perfect, simplistic answer of why we would want an immutable object. We have our departments budget data to be used be something such as a grid or a chart. After it is created, there is no reason for to ever change any of these fields. When it comes to creating your objects, it is always a good rule to limit as much as possible. It is less for you to manage and gives the person using the object less of a chance to screw it up in one way or another.

Update. Thanks to Alex Miller for pointing this out.
*If you do decide you need a setter object, you must make sure that your setters returns a new object. If we look at our example, lets say for some reason you did want to change the budget, you could add setting method like this:

public final DepartmentBudgetData addToBudget(double value){
    double budget = _budget + value;
    return new DepartmentBudgetData(budget,_name,_date);
}

Advantages of immutable objects

Alright so a lot of people will ’see’ it, but not really understand the advantages that it holds to making your objects immutable. However, there are a few advantages that you get right off the bat. One of the great advantages are that immutable objects are thread safe. Why? Because the values will never change. They are free to be read at any time by anyone and require no synchronization.

They are great for reusable constants objects. I can’t take credit for this example, but I feel its a good example. Math classes are always good for important constants objects. Let’s say you have an object for Complex numbers and its constructor takes in a real number and an imaginary number. You can use your immutable object to represent certain constants such as the following:

public static final Complex ZERO = new Complex(0,0);
public static final Complex ONE = new Complex(1,0);
public static final Complex I = new Complex(0,1);

While this is a simple example, it does show how easily one can create static constants with the object. They also be made more useful by utilizing a static factory method to create the objects, which bring me to the next advantage

They are great for caching. With the values being unique per object, it makes caching simple. If you were to employ the use of a static factory method, if you want to avoid uselessly creating multiple objects, you could check to see if the object has already been created. If it has been, just returned the cached value.

Disadvantage of immutable objects

Of course, everything does have a disadvantage. You might have already guessed it. Since immutable objects will always have just one value, we do run the risk of creating a large amount of these objects. This becomes even more dangerous if it is costly to create these objects. Not everything is as easy as passing in a name, date and value. In this instance, a caching layer may not do us any good. One way we can get around this is by using a companion class. Going back to our previous example, lets say that it took a lot of work to generate that value for our departments budget. We dont want to keep creating immutable objects at each stage of creating that. What we want is something that will do all the steps for us and when it is done, it will return an immutable object.

public class MutableDepartmentBudgetData {
    private double _budget;
    private String _name;
    private Date _date;
    public MutableDepartmentBudgetData(String name, Date date){
        ...
        ...
    }
    public generateValueFromFoo(double value){
        //generate something
        _budget = ...
    }
    public generateValueFromBar(double value){
        //generate something else
        _budget =...
    }
    public DepartmentBudgetData getImmutableDepartmentBudgetData(){
        //magic happens here
        return new DepartmentBudgetData(_budget, _name,_date);
    }
 
}

When we use a companion class, we can use that object to go through all the steps required to generate our values. If we didnt do this, we would have to create an immutable object through each step of generating the values.

When creating our classes, we want to limit our accessibility as much as possible. When creating your objects, try to ask yourself ‘Why would I never need to change this value?’ If you take away the ability to modify that object, the less chance there will be of those values being incorrect. If you need the setter to be there, make sure that you have an extremely good reason for it. If you are doing anything with threading, it is best to use them since the values WILL NOT CHANGE after the constructor has initialized them. Further more, they are great for caching since the values never change and you can just cache the instance. While it is preferred to that you use immutable objects, you still need too be aware of the requirements of the project. They are great but there are some places where it is just not feasible to use them.

Marcel Best Practices, Learn This, Opinion , , ,

  1. February 24th, 2009 at 14:35 | #1

    Immutable classes are indeed quite important but I wanted to mention a few things:

    1) You mention the importance of marking fields final but you didn’t actually do so in your example. This is of critical importance to the Java Memory Model.

    2) Regardless of final usage, this class is actually not immutable. You return the Date field from the getter and Date is a mutable class that the caller of the getDate() can modify, thus modifying the data of this class. It is best to either wrap objects like this in immutable wrappers or copy the data so it cannot reach back to you.

    3) Examples like your “constants” are usually better implemented with an enum in Java, although it depends a bit on the usage.

    4) Even setters are ok for an immutable class…as long as they return a new immutable copy of the object. See BigInteger/BigDecimal for good examples.

    5) Your “companion class” pattern is more commonly called a Builder.

  2. February 24th, 2009 at 14:41 | #2

    Alex,

    Good catch on the Date. I cant believe I let that slip through because I have definitely run into that situation before. However, I did opt for making the whole class final in the example. You are right though, for the purpose of this example, I should have marked all of them as final instead.

    I agree on the setters being okay and as you said, they are fine as long as they return new instances of your class. In the example I gave, there wasnt too much of a reason for it. But I suppose for the purpose of an example I can throw an example up there.

    Thanks for the input!
    Marcel

  3. February 24th, 2009 at 14:58 | #3

    Nice introduction on immutable objects. I use immutable objects to implement Value Object (see DDD).

  4. February 25th, 2009 at 22:00 | #4

    Marking the fields final is far more important than marking the class final. These two things are completely different. Marking the fields final indicates special things in the Java Memory Model – namely that the value MUST be set by the end of construction (or you will get a compile error) and if the object is safely published, all threads are guaranteed to see the values you set during the constructor *without further synchronization*. Without the final on the fields, those guarantees are not given by the JMM.

  5. willcodejavaforfood
    March 10th, 2009 at 10:59 | #5

    I’d say that getters must return immutable objects or copies is important enough that is should be in the bullet point list. :)

  6. Himanshu
    June 14th, 2010 at 11:28 | #6

    The example is still not immutable.
    In the constructor you take Date as a parameter, so when someone instantiates this, it would be passed in. So the reference is held outside and can be modified post object creation. So the immutable parameters in the constructors should be cloned before assigning to private instance variables.

  1. March 24th, 2009 at 12:32 | #1