Code Pumpkin

How to create Immutable Class in Java

Subscribe

Immutable class is a class which once created, it's contents can not be changed. Immutable objects are the objects whose state can not be changed once constructed. 

In Java, String  and all the wrapper classes e.g. Boolean, Integer, Long, etc are immutable classes. We can create our own immutable class as well.

Joshua Bloch's Effective Java has a very good explanation about why you should make your classes Immutable unless there is a strong reason to make them mutable.

Immutable Class from Effective Java

As per the guidelines provided in book, if a class cannot be made immutable, limit its mutability as much as possible.

Why should we write Immutable Classes?

Here are some of the advantages of Immutable Classes.

  1. Since the state of the immutable objects can not be changed once they are created, they are automatically synchronized/thread-safe and the overhead caused due to use of synchronization is avoided.
  2. The references to the immutable objects can be easily shared or cached without having to copy or clone them as their state can not be changed ever after construction.
  3. Immutable objects are good Map keys and Set elements, since they do not change once created.

Creating an Immutable class

Following are the requirements:

  1. Classmust be declared as final. (So that child classes can’t be created)
  2. Data members in the class must be declared as final and private (So that we can’t change their values after object creation)
  3. A parameterized constructor 
  4. No setters (To not have option to change the value of the data members)
  5. Getter method for all the variables in it

For Example,

Let's create simple immutable User Object which is having only two fields :username and password


public final class User {
    private final String username;
    private final String password;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }
}

In most of the classes in our real applications, there are more than two fields. Also, most of these fields are not mandatory for object creation.

For example, a User in a real application will have a username, password, firstName, lastName,  emailAddress, etc., but for user creation here, only a username and password are required. So, we design our class as shown below:


public final class User {
    private final String username;
    private final String password;
    private String firstname;
    private String lastname;
    private String email;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
}

This class is not fully immutable because it has mutators, i.e. setters. So, instances of this class can be modified after creation. 

This approach has the disadvantage that objects can be in an inconsistent state  and you have to put in extra effort to ensure thread safety.

In such cases, you should use Builder Design Pattern to achieve immutability.

According to GOF:

The Builder Pattern separates the construction of a complex object from its representation so that the same construction process can create different representations.

The builder design pattern provides a way to build complex immutable objects. The process is:

  1. The client calls a constructor with all the required fields and gets a builder object.
  2. The client calls setter like methods to set each optional parameter of interest.
  3. Finally the client calls the build method to generate the new object which is immutable.

Let's modify our User object using Builder Design Pattern:


public class ImmutableUser {
    private final String username;
    private final String password;
    private final String firstname;
    private final String lastname;
    private final String email;

    private ImmutableUser(UserBuilder builder) {
        this.username = builder.username;
        this.password = builder.password;
        this.firstname = builder.firstname;
        this.lastname = builder.lastname;
        this.email = builder.email;
    }

    public String getUsername() {
        return username;
    }
    public String getPassword() {
        return password;
    }
    public String getFirstname() {
        return firstname;
    }
    public String getLastname() {
        return lastname;
    }
    public String getEmail() {
        return email;
    }

    public static class UserBuilder {

        private final String username;
        private final String password;
        private String firstname;
        private String lastname;
        private String email;

        public UserBuilder(String username, String password) {
            this.username = username;
            this.password = password;
        }
        public UserBuilder firstName(String firsname) {
            this.firstname = firsname;
            return this;
        }
        public UserBuilder lastName(String lastname) {
            this.lastname = lastname;
            return this;
        }
        public UserBuilder email(String email) {
            this.email = email;
            return this;
        }
        public ImmutableUser build() {
            return new ImmutableUser(this);
        }
    }
}

Client Code:


public class CodePumpkinDemo {
	public static void main(String[] args) {
		ImmutableUser user = new ImmutableUser.UserBuilder("pumpkin", "password")
                                .firstName("Pumpkin")			
                                .lastName("PapaPumpkin")
                                .email("pumpkin@codepumpkin.com")
                                .build();
	}
}

That's all about Immutable Classes.

Happy Learning smiley

Tags: , , , , ,


Comments and Queries

If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code class="java"> 
String foo = "bar";
</code></pre>
For more information on supported HTML tags in disqus comment, click here.

Total Post : 80
Subscribe
Contribute Your Articles

Interview Experiences

Related Books

Like Us On Facebook

Alexa Page Rank