Java中很多class都是immutable,像String,Integer等,它们通常用来作为Map的key.
那么在实现自定义的Immutable的Class的时候,应该注意哪些要点呢?
a)Class 应该定义成final,避免被继承。
b)所有的成员变量应该被定义成final。
c)不要提供可以改变类状态(成员变量)的方法。【get 方法不要把类里的成员变量让外部客服端引用,当需要访问成员变量时,返回成员变量的copy】
d)构造函数不要引用外部可变对象。如果需要引用外部可以变量,应该在构造函数里进行defensive copy。
- Wrong way to write a 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();
- }
- }
- // the caller could 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);
- Out put:
- Before constructing Numbers are: 1 2
- After constructing Numbers are: 1 5
- Right way to write an immutable class
- 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.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 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);
- Out put:
- Before constructing Numbers are: 1 2
- After constructing Numbers are: 1 2