Tuesday, September 3, 2024

How to make Immutable class in Java? Mutable vs Immutable Objects

How I make immutable objects in Java? I've always thought that all objects are immutable, because if you change the content of an String example, it will always create you an new String object and point to that. However later I found that String is a special class and its specially designed as an Immutable class because its often cached. Obviously you cannot cache anything which is not constant and that make sense why String is Immutable in Java. But this encouraged me to learn more about Mutable and Immutable class in Java and how to create a custom Immutable class in Java.


For example, how can I make my Order, Trade, Player, User, or any random Object Immutable? If you also have same doubt then you have come to the right place. 

In this article, I will not only share steps to make your class Immutable in Java but also talk about Mutable vs Immutable objects and their pros and cons. This is also a popular String interview question and Java developer should be aware of that as well.  


What is Mutable and Immutable class in Java?

In Java, the concepts of mutable and immutable classes refer to whether the state of an object can be changed after it has been created or not. A mutable class is a class whose instances can be modified after they are created, while you cannot change the state of an Immutable class once created. 

The state of a mutable object can be changed through its methods by modifying its fields or properties. For example, StringBuilder and ArrayList are mutable classes. For instance, you can append, delete, or modify elements in a StringBuilder or an ArrayList.

StringBuilder mutableString = new StringBuilder("Hello");

mutableString.append(", World!"); // Mutable operation

System.out.println(mutableString.toString()); // Outputs: Hello, World!

An Immutable class is a class whose instances cannot be modified after they are created. The state of an immutable object is set during its construction and cannot be altered afterward. For example,  String and Integer are examples of immutable classes. Once a String object is created, you cannot change the characters it contains.
String immutableString = "Hello";

// Immutable operation - returns a new String,
// but doesn't modify the original
immutableString.concat(", World!"); System.out.println(immutableString); // Outputs: Hello

So, you should now know that an immutable object is just an object that has no content that can be changed. A couple of examples are a class with all fields final, or a class with all private fields and no setters. Since the fields are final or private, they can never be externally changed. This makes them immutable.

 A mutable class, on the other hand, allows it's contents to be changed. For example a class with non-final fields, or private fields with setters. Since external code can change the contents of the class, the class is mutable.

Immutable classes like can also be cached like String which is cached in a special String pool in Java mainly to save memory and allow reuse of String literals, here is a nice diagrams which shows how Strings are saved and used from String pool in Java:

String pool in Java with Immutable object



How to create an Immutable class in Java?

Now that we know what is Mutable and Immutable classes in Java, it's time to find out how to write an Immutable class and how different it is from creating a Mutable class. Well, the only difference is in how you write them. 


Here is an example of an immutable class:


public class CustomImmutableClass {

    public final String customString = ""; //field is final, so it cannot be changed

    private int customInt = 0; //field is private and has no setter, so it cannot be changed



    public int getCustomInt() {

        return customInt;  //CustomInt can be retrieved, but not set.

    }

}

And here is an example of a mutable class:

public class CustomMutableClass {

    public String customString = ""; //field is NOT final, so it CAN be changed

    private int customInt = 0; //field is private and has a setter, so it CAN be changed



    public int getCustomInt() {

        return customInt;  //CustomInt can be retrieved

    }



    public void setCustomInt(int customInt) {

        this.customInt = customInt; //customInt can be set

    }

}

Immutable classes should be marked as final class so they can't be extended but just making a class final doesn't make it Immutable, especially if it can leak state like returning an Object which is not final and part of state. Also, having public final fields is bad form.

Strings are immutable, most objects are not. Whenever you have a mutator method (setSomething or addSomething)

that returns void chances are good that the object is mutable. An prominent example of that is ArrayList, you can observe this behaviour by storing 2 references to the List, both will change when valuea are added/removed from either

To make you objects immutable make sure they only have final fields that are not arrays (arrays are always mutable in java) and all the types of the fields also only have final fields. You can have non final fields if you disallow access/mutation to them, this is non trivial to reason about though (but most of the time it is easier).


Difference between Immutable vs Mutable objects in Java

Here are some key difference between between Mutable and Immutable Classes in Java:

1. Modification
Mutable object can be modified after creation but Immutable objects cannot be modified after creation.

2. Thread Safety
Mutable objects are not thread safe and may require synchronization if used in a multithreaded environment to avoid data corruption. On the other hand Immutable objects are generally thread-safe, as the state cannot change and can be safely shared between multiple threads. 

3. State Changes
Mutable objects allows for changes in state but Immutable object's state is fixed upon creation.


4. Use Cases
Mutable objects are useful when you need to modify the object frequently or when you want to represent entities whose state can change over time. On the other hand Immutable objects are useful when you want to ensure that the state of an object remains constant or when you need thread safety.

5. Performance
Mutable object can have better performance in certain scenarios due to direct modification of state, but Immutable object may involve creating new objects, potentially impacting performance, but offers advantages in terms of safety and simplicity.

So, that's all about difference between Mutable and Immutable objects in Java but we are not done yet, here is a quiz for you which is based upon the concept of Immutability see if you can answer it correctly:

How to make Immutable class in Java? Mutable vs Immutable Objects


That's all about Immutable and mutable classes in Java. In this article, not just learned what is Mutable and Immutable class but also learned the difference between them. Choosing between mutable  and immutable classes depends on the specific requirements of your program and the characteristics you need for the objects in question. Immutable classes are often preferred in concurrent or multithreaded environments and can simplify reasoning about the state of objects.


Other Java String articles You may like:

  • Why was the String class made final in Java? (answer)
  • How substring method of String works in Java? (answer)
  • Why char[] is better than String for storing a password in Java? (answer)
  • 10 Things Every Java Programmer should know about String? (answer)
  • How String in switch case works in Java 7? (answer)
  • How to format String in Java? (answer)
  • How to join String in Java 8 (example)
  • 15 Java Stream and Functional Programming interview questions (list)
  • How to check if String is null or empty in Java? (solution)

Thanks for reading this article so far. If you have any question or feedback then please drop a note note, happy to answer any query you may have. 

No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.