Immutable Class

Immutable objects are instances whose state doesn’t change after it has been initialized. For example, String is an immutable class and once instantiated its value never changes.Everytime we try to append() or concatenate() something with String it creates a new String but it does not change the same String.

Benefits of Immutable Class

1) Immutable class is good for caching purpose because you don’t need to worry about the value changes.
2) Other benefit of immutable class is that it is inherently thread-safe, so you don’t need to worry about thread safety in case of multi-threaded environment.

How to make immutable class
  • Declare the class as final so it can’t be extended.
  • Make all fields private so that direct access is not allowed.
  • Don’t provide setter methods for variables
  • Make all mutable fields final so that it’s value can be assigned only once.
  • Initialize all the fields via a constructor performing deep copy.
  • Perform cloning of objects in the getter methods to return a copy rather than returning the actual object reference.
Lets go through with an example to make the above points more clear.
    
public final class Employee{  
    final String pancardNumber;  
      
    public Employee(String pancardNumber){  
    this.pancardNumber=pancardNumber;  
    }  
      
    public String getPancardNumber(){  
    return pancardNumber;  
    }  
      
    }  

Now we will go through the few questions which would help us in making things more clear :

Que : What would happen if we keep all the properties of immutable class but does not make it final as below . How can the immutability of class can be broken .
class Card {
  private final Rank rank;
  private final Suit suit;
  public Card(Rank rank, Suit suit) {
    this.rank = rank;
    this.suit = suit;
  }
  public Rank getRank() {
    return rank;
  }
  public Suit getSuit() {
    return suit;
  }
  public int getValue() {
    return rank.getValue();
  }
}

If we are not making the class final then there will be no effect on the immutability of this particular class. But this class can be extended by other class and can totaly ignores the parent state and replace with it owns, mutable state . See the code as below : 

public class MyCard extends Card {
    private Rank myRank;
    private Suit mySuit;

    public MyCard(Rank rank, Suit suit) {
        this.myRank = rank;
        this.mySuit = suit;
    }

    @Override public Rank getRank() { return myRank; }

    public void setRank(Rank rank) { this.myRank = rank; }

    @Override public Suit getSuit() { return mySuit; }

    public void setSuit(Suit suit) { this.mySuit = suit; }

    @Override public int getValue() { return myRank.getValue(); }
}

Now the class that use Card in polymorphic context can't depend upon its being immutable.
 

Above Card class can be used between thread without worrying about data and race conditions.But if we override the Card class and ignores the immutable property and make mutable class, then a lot of issue could arise :
1) Now instances of MyCard aren't safe to share between threads, because they're not immutable. But the code doing the sharing may only know about them as instances of Card. leading them into a false sense of security.
2) The same goes for caching - it should be safe to cache and reuse immutable types, right? Well, it is safe to cache instances which are genuinely of an immutable type - but if you're dealing with a type which itself doesn't allow mutation, but does allow subclasses, it's suddenly not safe any more.

Que : If  we make our immutable class as below, where we have kept all the properties of immutable class but have not made member variable final.  Would it still be final or immutability can be broken here .



Que : What would happen if we do provide setter method for data member .

Que: What would happen if we make our member final and do not provide setter method but make them public ?


Que : What would happen if we have mutable object in our immutable class . How do we ensure immutability here ?




As per the output above ,we can see that the even after changing the value of local variables and mutable ref fetched from instance , instance value remains the same.

Comments

Popular posts from this blog

Deploy standalone Spring MVC Application in Docker Container

Refactor Code : Separate Query from Modifier

HTTP : Must known Protocol (Part 1)