How Mutable is an Immutable class?

The  common interview question - What is an immutable class and how would you write an immutable class in Java?

The common interview answer - An immutable class is one whose instance, once created, cannot be modified. The infamous example is the String class. To implement an immutable class, we mark the class final, lest it is extended by any other class, mark the member variables private and remove the setters.

The 'Not-So-Common' addendum to the question - Assume that the getter returns an object reference and the developer modifies the reference. Dosen't that mean that the original supposedly immutable class is modified?

 (eg)  Assume we try to implement an immutable class A as follows:

public final class A {
    private B b;
    public A(B b)
    {
        this.b = b;
    }
    public B getB()
    {
        return b;
    }
}

class B {
    int i;
    public B() {
     }
    public B(int i) {
        this.i = i;
    }
    public void set(int i) {
        this.i = i;
    }
    public int get() {
        return i;
    }
}

Class A is final and has no setter. It is supposedly immutable, However it has a reference to an object B. If someone does the following:

        B b = new B(5);
        A t = new A(b);
        B b1 = t.getB();
        System.out.println(t.getB().get());
//prints 5
        b.set(6);
        System.out.println(t.getB().get());
//prints 6
        b1.set(7);
        System.out.println(t.getB().get());
//prints 7

So since we have the references to the B object (i) that is passed to the constructor and (ii) that is obtained from the getter, Class A is not completely immutable. While these references are modified externally, the object that A has is modified, thus rendering A mutable.

The actual question : How can A be made completely immutable?

A possible (usually expected) answer: In the constructor of the immutable class, have make copies of the objects that are passed and store the copied objects, not the passed object reference.Similarly in the getter of the immutable class, make a copy of the to-be-returned object and return the copy, not the stored object.

So the actual immutable code would look something like:

public final class Test {
    private B b;
    public Test(B b1)
    {
        this.b = new B();
        this.b.set(b1.get());
    }
    public B getB()
    {
        B b1 = new B();
        b1.set(this.b.get());
        return b1;
    }

Now, on running

        B b = new B(5);
        A t = new A(b);
        B b1 = t.getB();
        System.out.println(t.getB().get());
//prints 5
        b.set(6);
        System.out.println(t.getB().get());
//prints 5
        b1.set(7);
        System.out.println(t.getB().get());
//prints 5

Now that class was a little less mutable :)

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

nitkal

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
Bookmarks