The design of Java immutable class

1.1 immutable class

Immutable class refers to a class whose state cannot be modified after an instance is created. Their instance information is provided when the constructor is called and is fixed throughout the object's life cycle.

 

1.1.1 benefits of immutable classes

In the Java platform class library, there are many immutable classes, such as String, basic type wrapper class and Unmodifiable corresponding to the implementation of various Collections in the Collections tool class. Immutable classes are easier to design, implement and use than mutable classes. They are less prone to errors and more secure.

  • Immutable objects are simple because there is only one state (the state at the time of creation)
  • Immutable objects can be freely shared
  • Immutable objects must be thread safe, they don't need extra synchronization

 

1.1.2 design rules for immutable classes

  • No value setting method is provided for modifying object state externally
  • All domains declared are of type final^
  • Ensure that the class will not be extended and created correctly

Note: not all fields must be declared as final type. For details, please refer to the hash field in String class. Even if all fields in the object are of final type, it cannot be guaranteed that the object is immutable, because in the field of final type, it may point to the mutable object.

 

1.1.3 specific design of immutable class

public class ImmutableClass {
	
	private final int x;
	private final int y;
	
	private int hash; // Cache hashcode. Internal calculation may change but no value setting method will be provided
    
    // The final domain points to a mutable object and cannot return the object reference ❌
	// private final List<Integer> list = new ArrayList<>();
        private final List<Integer> list = Collections.unmodifiableList(Arrays.asList(1,2));
	
	/*
	 * Cache object, final can be omitted because it is a private constructor
	 */
	public static final ImmutableClass ZERO_ONE = new ImmutableClass(0, 1);
	public static final ImmutableClass ONE_TWO = new ImmutableClass(1, 2);
	
	// Using static factory method + private constructor to make the class final
	private ImmutableClass(int x, int y) {
		this.x = x;
		this.y = y;
	}
	public static ImmutableClass valueOf(int x, int y) {
		return new ImmutableClass(x, y);
	}
	 
	public ImmutableClass plus(ImmutableClass u) {
		return new ImmutableClass(x + u.x, y + u.y);
	}
	
	public ImmutableClass minus(ImmutableClass u) {
		return new ImmutableClass(x - u.x, y - u.y);
	}
	
	//....
	
	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
	public List<Integer> getList() {
		return list;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == this)
			return true;
		if (!(obj instanceof ImmutableClass))
			return false;
		ImmutableClass u = (ImmutableClass)obj;
		return Integer.compare(u.x, x) == 0
			&& Integer.compare(u.y, y) == 0;
	}
	
	@Override
	public int hashCode() {
		int result = hash;
		if (result == 0) {
			result = Objects.hash(x,y);
			hash = result;			
		}
		return result;
	}
	
}

 

summary

If an object cannot be modified after it is created, it is called an immutable object. The only disadvantage of immutable classes is that they need to create a new object for each different value.  

Tags: Java less

Posted on Wed, 06 Nov 2019 10:33:54 -0500 by DeathfireD