|
Wrong way to write an immutable class
|
Right way to write an immutable class
|
|
Wrong way to write a constructor:
|
Right way is to copy the array before assigning in the constructor.
|
|
public
final class
MyImmutable
{
private final
int[] myArray;
public MyImmutable(int[] anArray)
{
this.myArray = anArray; // wrong
}
public String toString()
{
StringBuffer
sb = new StringBuffer("Numbers are: ");
for (int
i = 0; i < myArray.length; i++)
{
sb.append(myArray[i]
+ " ");
}
return sb.toString();
}
}
|
public final
class MyImmutable
{
private final
int[] myArray;
public MyImmutable(int[] anArray)
{
this.myArray
= anArray.clone(); // defensive copy
}
public String toString()
{
StringBuffer sb = new StringBuffer("Numbers are: ");
for (int i = 0; i < myArray.length; i++)
{
sb.append(myArray[i] + " ");
}
return sb.toString();
}
}
|
|
// the caller could change the array after calling the constructor. |
// the caller cannot change the array after calling the constructor. |
|
int[] array = {1,2};
MyImmutable myImmutableRef
= new MyImmutable(array) ;
System.out.println("Before
constructing " + myImmutableRef);
array[1] = 5; // change
(i.e. mutate) the element
System.out.println("After
constructing " + myImmutableRef);
|
int[] array = {1,2};
MyImmutable myImmutableRef
= new MyImmutable(array) ;
System.out.println("Before
constructing " + myImmutableRef);
array[1] = 5; // change
(i.e. mutate) the element
System.out.println("After
constructing " + myImmutableRef);
|
Out put:
Before constructing Numbers are: 1 2
After constructing Numbers are: 1 5
As you can see in the output that the “MyImmutable” object has been mutated. This
is because the object reference gets copied |
Out put:
Before constructing Numbers are: 1 2
After constructing Numbers are: 1 2
As you can see in the output that the “MyImmutable” object has not been mutated. |
Wrong way to write an accessor. A caller could get the array reference and then
change the contents |
Right way to write an accessor by cloning. |
|
public int[] getArray()
{
return myArray;
}
|
public int[] getAray()
{
return (int[]) myArray.clone();
}
|