Wednesday, September 4, 2024

How to create Immutable Class and Object in Java - Tutorial Example

Writing or creating immutable classes in Java is becoming popular day by day, because of the concurrency and multithreading advantage provided by immutable objects. Immutable objects offer several benefits over a conventional mutable object, especially while creating concurrent Java applications. Immutable object not only guarantees safe publication of object’s state but also can be shared among other threads without any external synchronization. In fact, JDK itself contains several immutable classes like String, Integer, and other wrapper classes. 

For those, who don’t know what is immutable class or object is, Immutable objects are those, whose state can not be changed once created like java.lang.String, once created can not be modified like trim, uppercase, lowercase.

All modifications in String result in the new objects, see why String is immutable in Java for more details. In this Java programming tutorial, we will learn, how to write an immutable class in Java or how to make a class immutable.

By the way, making a class immutable is not difficult on the code level, but its the decision to make, which class is mutable or immutable which makes a difference. I also suggest reading, Java Concurrency in Practice to learn more about concurrency benefits offered by Immutable objects.

And, If you are new to Java then you can also check out these free Java programming courses to learn Java from scratch in a guided and structured way. This is one of the best free, and up-to-date courses to learn Java online.



What is an immutable class in Java? Example

As said earlier, Immutable classes are those classes, whose object can not be modified once created, it means any modification on an immutable object will result in another immutable object. the best example to understand immutable and mutable objects are, String and StringBuffer

Since A string is an immutable class, any change on existing string object will result in another string e.g. replacing a character into String, creating substring from String, all result in new objects. 

While in case of mutable object like StringBuffer, any modification is done on object itself and no new objects are created. 

Some times this immutability of String can also cause security hole, and that the reason why password should be stored on char array instead of String.


Here are some important properties of Immutable class in Java:

What is an immutable class in Java? Example



How to write Immutable class in Java?

Despite a few disadvantages, an Immutable object still offers several benefits in multi-threaded programming and it’s a great choice to achieve thread safety in Java code. here are few rules, which helps to make a class immutable in Java :

1. The state of immutable object can not be modified after construction, any modification should result in a new immutable object.

2. All fields of the Immutable class should be final.

3. Object must be properly constructed i.e. object reference must not leak during construction process.
4. Object should be final in order to restrict sub-class for altering immutability of parent class.

By the way, you can still create an immutable object by violating few rules, like String has its hashcode in the non final field, but its always guaranteed to be the same. No matter how many times you calculate it because it’s calculated from final fields, which is guaranteed to be the same. 

This required a deep knowledge of Java memory model, and can create subtle race conditions if not addressed properly. In next section we will see simple example of writing immutable class in Java. 

By the way, if your Immutable class has lots of optional and mandatory fields, then you can also use Builder design pattern to make a class Immutable in Java.

Builder design pattern explained



Immutable Class Example in Java

Here is complete code example of writing immutable class in Java. We have followed simplest approach and all rules for making a class immutable, including it making class final to avoid putting immutability at risk due to Inheritance and Polymorphism.

public final class Contacts {

    private final String name;
    private final String mobile;

    public Contacts(String name, String mobile) {
        this.name = name;
        this.mobile = mobile;
    }
  
    public String getName(){
        return name;
    }
  
    public String getMobile(){
        return mobile;
    }
}

This Java class is immutable because its state can not be changed once created. You can see that all of it’s fields are final. 

This is one of the most simple ways of creating immutable classes in Java, where all fields of class also remain immutable like String in the above case. 

Sometimes you may need to write an immutable class that includes mutable classes like java.util.Date, despite storing Date into the final field it can be modified internally if the internal date is returned to the client. 

In order to preserve immutability in In such cases, it's advised to return a copy of the original object, which is also one of the Java best practices. here is another example of making a class immutable in Java, which includes mutable member variables.

public final class ImmutableReminder{
    private final Date remindingDate;
  
    public ImmutableReminder (Date remindingDate) {
        if(remindingDate.getTime() < System.currentTimeMillis()){
            throw new IllegalArgumentException("Can not set reminder” +
                        “ for past time: " + remindingDate);
        }
        this.remindingDate = new Date(remindingDate.getTime());
    }
  
    public Date getRemindingDate() {
        return (Date) remindingDate.clone();
    }
}

In above example of creating immutable class, Date is a mutable object.

If getRemindingDate() returns actual Date object than despite remindingDate being final variable, internals of Date can be modified by client code. 

By returning clone() or copy of remindingDate, we avoid that danger and preserves immutability of class.



Benefits of Immutable Classes in Java

What is Immutable class and object, how to create Immutable in Java with exampleAs I said earlier Immutable classes offers several benefits, here are few to mention:

1) Immutable objects are by default thread safe, can be shared without synchronization in concurrent environment.

2) An immutable object simplifies development, because its easier to share between multiple threads without external synchronization.

3) Immutable object boost performance of Java application by reducing synchronization in code.

4) Another important benefit of Immutable objects is reusability, you can cache Immutable object and reuse them, much like String literals and Integers.  

You can use static factory methods to provide methods like valueOf(), which can return an existing Immutable object from cache, instead of creating a new one.

5) Immutable classes and functions are also key to write functional programming code. 

Apart from the above advantages, immutable object has disadvantage of creating garbage as well. 

Since the immutable objects can not be reused and they are just a use and throw. String being a prime example, which can create lot of garbage and can potentially slow down application due to heavy garbage collection, but again that's extreme case and if used properly Immutable object adds lot of value.

That's all on how to write immutable class in Java. we have seen rules of writing immutable classes, benefits offered by immutable objects and how we can create an immutable class in Java that involves mutable fields. 

Don’t forget to read more about the concurrency benefit offered by Immutable object in one of the best Java books recommended to Java programmers, Concurrency Practice in Java.


Related Java programming concepts and tutorials


37 comments:

  1. Hi Javin,
    Nice article , Just want to add few more things..

    1) All the fields must be private and preferably final
    2) Ensure the class cannot be overridden - make the class final, or use static factories and keep constructors private
    3) Fields must be populated from the Constructor/Factory
    4) Don't provide any setters for the fields
    5) Watch out for collections. Use Collections.unmodifiable*. Also, collections should contain only immutable Objects
    6) All the getters must provide immutable objects or use defensive copying
    7) Don't provide any methods that change the internal state of the Object

    Guys please also refer to this url.. http://www.javaranch.com/journal/2003/04/immutable.htm

    ReplyDelete
  2. Hi Javin,

    Thanks for posting such very useful posts.

    It would have been very very useful if the site consists a search option to check for a particular topic in specific.

    ReplyDelete
  3. One more thing that I would like to add Javin regarding the example shown that is..

    we should make a copy of remindingDate.getTime() BEFORE checking it against your class invariants. Otherwise an attacker with a reference(long time = remindingDate.getTime();) to your remindingDate could call a .set method on it to change the value after you've checked it's validity.The program should be like ...

    public final class ImmutableReminder{
    private final Date remindingDate;

    public ImmutableReminder (Date remindingDate) {
    long incomingTime = remindingDate.getTime()

    if(incomingTime < System.currentTimeMillis()){
    throw new IllegalArgumentException("Can not set reminder” +
    “ for past time: " + remindingDate);
    }
    this.remindingDate = new Date(incomingTime);
    }

    public Date getRemindingDate() {
    return (Date) remindingDate.clone();
    }
    }

    ReplyDelete
  4. @Saral, Once again great comment. Your point is perfectly valid while using mutable class like Date here, This once again highlight, importance of Immutable classes for security reasons as well.

    ReplyDelete
  5. Thanks Javin..One must think before making an class as immutable as we know..

    1) With immutability, any time you need to modify data, you need to create a new object. This can be expensive.

    2)Reflection based frameworks are complicated by immutable objects since they requires constructor injection

    3)constructor argument names are not usually available through reflection, which forces us to depend on argument order for dependency resolution

    ReplyDelete
  6. How do you decide to make a class Immutable in Java? I understand about value classes like String, Integer, but again How about java.util.Date, should that's a value class, should it should be immutable. Why Java designer keeps java.util.Date mutable, please advise.

    ReplyDelete
  7. @Raj, there is Google search text box in top right. Did you try that?

    ReplyDelete
  8. Over the year, I learned that value object, which is usually domain specific must be immutable. Class es like Order, Trade, Customer, Product are couple of examples of value Object. Interestingly you should be having corresponding database table for them and each row is equal to one instance of value object.

    ReplyDelete
  9. Is making field final is necessary to create Immutable class? I guess when you make your class final, it means no one can sub class, which means no overriding of methods. Also if you don't provide setter than no one can modify state of object. What is the point of making member variable final inside Immutable class?

    ReplyDelete
  10. BigDecimal and BigInteger are also good example of Immutable classes from JDK.

    ReplyDelete
  11. Hi,

    You and your readers may be interested in an open source tool I created which allows you to test if your class is immutable or not. For example, you could have a JUnit test like this:

    @Test
    public void testIsImmutable() {
    MutabilityDetector.assertImmutable(Contacts.class);
    }

    Then, if someone came along and added a setter method, or took away the final modifiers, the test would fail. This would give you confidence that not only are you correctly writing an immutable class now, but if anyone accidentally breaks it later, they'll be notified.

    (Note that Mutability Detector would raise an error for ImmutableReminder by default, but that can be configured)

    ReplyDelete
  12. @Graham, Thanks for writing such a useful tool, that can definitely complement some one's Junit test. I wish, if static analyzers can also do that or you may wish to let them know about your open source tool. Anyway, great work, please share link with us.

    ReplyDelete
  13. Hi Javin,

    I have one Quick Question.If there is no Setter method then how will we set the value initially.

    ReplyDelete
  14. @Anonymous, value is initially set in constructor, when object is created. So Immutable object state remains same in its life.

    ReplyDelete
  15. Apart from the way mentioned here, is there any other way to make a class Immutable in Java?

    ReplyDelete
  16. Hi,
    We are creating our custom immutable class by the help of
    1)making the class as final
    2)providing the variable as final and initialize them in constructor
    3)and providing only the getter methods

    My doubt is String class is final and is immutable, I agree.But StringBuffer/StringBuilder class is also final that means it will not inherit by other class also.So internally what implementation has done so that it made the StringBuilder as mutable .
    Please clarify my doubt.

    ReplyDelete
  17. @jo I think that is a fair point for the class in question. However it may help to declare it final if you have some methods which uses these variables within the class to prevent from modifying it as compiler would complain in that case

    ReplyDelete
  18. Is it require that immutable class must have Private constructor? I think no. As String in immutable class and we can create as many objects of it. But still in interviews people are asking why and why not to create the private constructor? Please help me to resolve my query.

    ReplyDelete
  19. Hi anonymous..


    I have one Quick Question.If there is no Setter method then how will we set the value initially.

    You can refere the below link for that: http://howtodoinjava.com/2012/10/28/how-to-make-a-java-class-immutable/

    You can pass the parameter value into the private constructor first time.

    ReplyDelete
  20. Please suggest the below scnario to make immutable

    public final class A{
    public final B c;
    public A(B c){
    this.c = c;
    }
    public B getB(){
    return c;
    }
    }

    // Look at the below code

    A a = new A(new B());

    s.getB().setC(c); // it is change the state of the object. how can overcome that one.

    ReplyDelete
  21. hi,i just read your post and i am little confused about the re-usability that you have explained in the point no (4).you have explained that it is re-usable in point no (4)_ and if you notice again in the para after point no (4) you have explained that it cannot be re-used.Please clarify it.

    ReplyDelete
  22. Hi, As Indhu specified, can you please explain the two contradicting statements :
    1. "4) Another important benefit of Immutable objects is reusability, "
    2. "Apart from above advantages, immutable object has disadvantage of creating garbage as well. Since immutable object can not be reused and they are just a use and throw."

    ReplyDelete
  23. Hi Javin,
    What is the necessity of making the member variables final?
    as anyways we are not providing any setters to alter the value,
    and in case of mutable fields, we are returning a clone to the callee.

    ReplyDelete
  24. @Ponselvan Francis Infant Anto . If you dont make the fields final, class methods could change the value of the private fields their by breaking the immutability.

    ReplyDelete
  25. Could some one explain me why fields has to be private? IMHO making them final would suffice .
    and Why are we making class final ? Subclass cann't change the values of Superclass in any manner. It only inherits the values from the Superclass. The reason for making String class was different . Jave guys dint want people to extend the functionality of String class , thats why they made it final. It will be very helpfull if someone shed light on this :)

    ReplyDelete
  26. Hi javin , its great work . I wann ur advice om this If class have reference variable as mutable class how can u make reference variable as immutable. ?

    ReplyDelete
  27. /* package whatever; // don't place package name! */

    import java.util.*;
    import java.lang.*;
    import java.io.*;

    /* Name of the class has to be "Main" only if the class is public. */
    public final class coffee{
    {
    /*private*/ public final String coffee;
    /*private*/ public final String code;
    public void coder(String coffee,String code)
    {
    this.coffee=coffee;
    this.code=code;
    }
    public String getcoffee()
    {
    return coffee;
    }
    public String getCode()
    {
    return code;
    }
    //do
    //{
    System.out.println("It's time to drink coffee");
    //}
    //While(coffee==coffee)
    }

    public static void main(String []args)
    {
    // System.out.println("Hello World");
    coffee c=new coffee();
    c.coder();
    }
    }
    Could any one help me to solve this code?
    Kinda getting errors and have doubt near do while block

    ReplyDelete
  28. I also like to use immutable value objects but they can be a hassle without tool support and the tools I could found had problems, so I just released my own open source tool for generating java value objects that used 100% standard java features and is extremely customisable. You can check it out at "http://valjogen.41concepts.com". Let me know what you think?

    ReplyDelete
  29. I like to add a point
    Immutable classes are best suited for keys in hashmap

    ReplyDelete
  30. You have declared these instance variable as final. Do you think blow code will work??

    public Contacts(String name, String mobile) {
    this.name = name;
    this.mobile = mobile;
    }

    ReplyDelete
    Replies
    1. Hi @Anonymous,

      yes the code will work absolutely fine, since the class variables have not been initialised at the time of declaration.
      These are called blank final variables.
      So for better understanding, read the concept of "Blank Final Variables"

      Delete

  31. public final class Contacts
    {
    private final String name;
    private final String mobile;

    public Contacts(String name,String mobile)
    {
    this.name=name;
    this.mobile=mobile;
    }
    public String getName()
    {
    return name;
    }
    public String getMobile()
    {
    return mobile;
    }
    private static void test(String name,String mobile)
    {
    name="santosh";
    mobile="1234";
    }
    public static void main(String[] args)
    {
    Contacts c=new Contacts("raman","9765434333");
    System.out.println(c.getName()+"---"+c.getMobile());
    test(c.getName(),c.getMobile());
    System.out.println(c.getName()+"--"+c.getMobile());



    }

    }

    ReplyDelete
  32. There are more than 10 instance variables in a class . What is the best way to make class immutable in java. Of course one way is to have a constructor with 10 parameter.

    ReplyDelete
  33. @Ajay, both are different problems, immutable class means you cannot change the state once created e.g. once you get the instance, its fixed. To solve the problem of constructor with multiple parameter, consider using Builder design pattern.

    ReplyDelete
  34. Hi Javin,

    Your blogs are awesome. I need clarification for the below situation:
    Based on your statement "Immutable objects are thread-safe",
    If I have a shared resource of type 'String' which is shared with multiple threads (say 3)
    And if one of the thread make changes to the shared reference, it will create a new String object and that will available only with that object and other threads will not get to know about the changes made.

    Will it not lead to data inconsistency.

    So could you please help me understand this?

    Thanks in advance.

    ReplyDelete
    Replies
    1. Declare the variable a volatile ,so that it's value could not going to be cache and each thread will get the value of that variable from main memory which is the latest value to make data consistent

      Delete