Search code examples
javafinal

What steps can you make to make a java object with a setter to be immutable?


What can you do to make an object such as this immutable? I am mostly concerned about solving public void someMethod(SomeObject someObject) { } <== This case

For example:

public class SomeObject {
   private String someString;

   public void setSomeString(String someString) {
      this.someString = someString;
   }
   public void getSomeString() {
      return someString;
   }
}


public void someMethod() {
   final SomeObject someObject = new SomeObject();
   someObject.set("Want to prevent this"); // <-- SomeObject is mutable in this case
}

public void someMethod(SomeObject someObject) {
   someObject.set("And prevent this!"); // <-- And so is this
}

Solution

  • You are right, declaring an object final does not make it immutable. All it does is preventing the final variable from being re-assigned a new object, but the object that is already assigned to it could be mutated if its mutating methods are available.

    You can give the object an interface that is immutable, and program to that interface:

    interface ImmutableCar {
        String getMake();
        String getModel();
    }
    class Car implements ImmutableCar {
        public Car(String make, String model) {
            this.make = make;
            this.model = model;
        }
        private String make;
        private String model;
        public String getMake() { return make; }
        public void setMake(String m) { make = m; }
        public String getModel() { return model; }
        public void setModel(String m) { model = m; }
    }
    

    If you do it like this

    ImmutableCar car = new Car("VW", "Bora");
    

    you would not be able to access mutating methods without an explicit cast. Of course this would not make the object truly immutable, because casting would remain a possibility, but then one could argue that other immutable objects can be changed by going through reflection, so this approach lets you expose only immutable behavior.