Constrain mutable object inside immutable Java object

I am studying immutable objects. I am trying to use this code

  public final class ImmutableObject {

    private final String name;

    private final NormalObject obj =  new NormalObject();

    public String getName() {
        return name;
    }


    public ImmutableObject(String name) {
        this.name = name;
        obj.setName(name);
    }


    public NormalObject getObj() {

        NormalObject tempObj = obj;
        return tempObj;
    }
}

public class NormalObject {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

      

I want to restrict the calling class to change the value of the variable name NormalObject

But the following code changes the meaning

 ImmutableObject obj = new ImmutableObject("Siddle");

 System.out.println(obj.getObj().getName()); //prints Siddle
 obj.getObj().setName("Kelly");

 System.out.println(obj.getObj().getName()); //prints Kelly

      

How to limit it?

+3


source to share


3 answers


For an object to be immutable, all of its properties must be immutable. His condition should not change.

To do this, you have to put an immutable facade on NormalObject

, you cannot directly return NormalObject

. The return method will also require a different return type, you cannot return NormalObject

, but in fact return something that doesn't behave like NormalObject

.

eg:.



public final class ImmutableObject {

    private final String name;

    private final NormalObject obj =  new NormalObject();

    private final ImmutableNormalObject objFacade = new ImmutableNormalObject(obj);

    public String getName() {
        return name;
    }

    public ImmutableObject(String name) {
        this.name = name;
        obj.setName(name);
    }

    public ImmutableNormalObject getObj() {

        return objFacade;
    }
}

public class NormalObject {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class ImmutableNormalObject {

    private NormalObject obj;

    public ImmutableNormalObject(Normalobject o) {
        this.obj = o;
    }

    public String getName() {
        return obj.getName();
    }
}

      

Alternatively, if it is acceptable to copy the object, and it has a copy constructor (or you can add one), you can do it, but copying and returning is expensive.

+5


source


You can do this by returning a copy of normalObject

yours to the getter:

public NormalObject getObj() {
    return new NormalObject(obj.getName());
    // or you can make a copy constructor:
    // return new NormalObject(obj);
}

      



Or you can make a wrapper for your own normalObject

, which ignores the name setter, but it slows down the logic.

0


source


Change your NormalObject code to

public final class ImmutableObject {

private final String name;
// initialise it to null
private final NormalObject obj = null;

public String getName() {
    return name;
}


public ImmutableObject(String name) {
    this.name = name;
    // use the Constructor for setting name only once during initialization of ImmutableObject via its constructor
    obj =  new NormalObject(name);

    //obj.setName(name);
}


public NormalObject getObj() {

    NormalObject tempObj = obj;
    return tempObj;
}

      

}

public class NormalObject {

private String name;
public NormalObject(name){
 this.name = name;
}
public String getName() {
    return name;
}
//Remove any setter on NormalObject
/*public void setName(String name) {
    this.name = name;
}*/

      

}

0


source







All Articles