`
darrenzhu
  • 浏览: 786053 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java不可变类或对象详解(Immutable class)

    博客分类:
  • Java
阅读更多

如果某个对象在被创建后其状态就不能被修改,那么这个对象就称为不可变对象。线程安全性是不可变对象的固有属性之一,它们的不变性条件是由构造函数创建的,只要它们的状态不改变,那么这些不变性条件就能得以维持。不可变对象一定是线程安全的。
当满足以下条件时,对象才是不可变的:
1) 对象创建以后其状态就不能修改。
2) 对象的所有域都是final类型(当然像不可变String类型的域并不需要声明为final)。
3) 对象是正确创建的(在对象的创建期间,this引用没有逸出)。

更多详细参考<Java Concurrency in Practice> 关于“不变性”的章节


Java实现Immutable Class要点

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);


Output:
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);


Output:
Before constructing Numbers are: 1 2
After constructing Numbers are: 1 2

Exercises:
1.What is Immutable class. How to make a Immutable class

2.If we make a class immutable and it has one List reference how do we make sure the list is not getting modified by other references.

3.Write a class that is Immutable.

4.Why do we make Immutable class final.

5.How do we declare setter and getter in immutable class, What is the need of Immutable class.

6.If we have date and timestamp class which is mutable and we want another lass which takes these two types and create a datetimestamp object how to make sure that it is immutable .
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics