Let’s understand the difference between String and StringBuffer or Mutable and Immutable classes.
Difference between String and StringBuffer
A String is an immutable class, which means, the state of its object cannot be modified once they are constructed whereas StringBuffer or StringBuilder is of mutable form which basically means that state modification of such objects is allowed
What do you mean by “modify the content” or mutable and immutable?
Immutable objects are the ones whose states can not be changed. When you want to create an Immutable class, make sure to follow these basic rules:
- All the fields should be private to avoid direct access.
- The class should be declared final so that it is not extended. Another approach could be to make the constructor private and construct instances in factory methods.
- All the mutable fields should be final so that the value is assigned only once.
- There should be no setter methods for variables.
- Field initialization should be done via constructors performing a deep copy.
- Return a cloned object from the getter instead of returning the actual object itself.
Example
// Make the class final
final public class ImmutableCake {
// final private fields
final private String flavor;
final private String name;
public ImmutableCake(String flavor, String name) {
this.flavor= flavor;
this.name = name;
}
public String getFlavor() {
return flavor;
}
public String getName() {
return name;
}
public ImmutableCake getCake() {
return new ImmutableCake("StrawBerry", "Bingo Straw");
}
}
So, What is the benefit of an immutable object over a mutable object?
Since immutable states can’t be modified they are particularly useful in concurrent applications. Since they can not change state, they are considered to be thread-safe. For example, consider these two statements –
// Mutable version
Cake cake = new Cake("Vanilla", "Vanilla Ice");
// Statement:1
String flavor = cake.getCakeFlavor();
// Statement:2
String name = cake.getCakeName();
Let us assume if another thread invokes cake.set() after Statement:1 but before Statement:2, the value of flavor won’t match the value of the name. To avoid this outcome, the two statements must be bound together like this –
synchronized (cake) {
String flavour = cake.getFlavor();
String name = cake.getName();
}
This kind of inconsistency is only possible for mutable objects. it will not be an issue for the immutable version of Cake as described above.
Further Readings
- https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html
- https://docs.oracle.com/javase/tutorial/essential/concurrency/syncrgb.html
Feel free to share your thoughts on this topic in the comments section below 👇 We would be happy to hear and discuss the same 🙂