不可变对象
共享对象想要安全发布,主要有两种方法,一种是额外同步的方法,另外则是将对象做为不可变对象。当满足一下条件时,对象才是不可变的:
- 对象创建以后其状态就不能修改
- 对象所有的域都是final类型
- 对象正确创建(在创建对象期间,this引用没有逸出)
安全发布一个对象,对象的引用以及对象的状态必须同时对其他线程可见,一个正确构造的对象可以通过以下方式安全发布:
- 在静态初始化函数中初始化一个对象引用
- 将对象的引用保存到volatile类型的域或AutomicReference对象中
- 将对象的引用保存到某个正确构造对象的final类型域中
- 将对象的引用保存到一个锁保护的域中
不可变对象具体:
- Declare the class as final so it can’t be extended.
- Make all fields private so that direct access is not allowed.
- Don’t provide setter methods for variables
- Make all mutable fields final so that it’s value can be assigned only once.
- Initialize all the fields via a constructor performing deep copy.
- Perform cloning of objects in the getter methods to return a copy rather than returning the actual object reference.
例子:
package com.journaldev.java;
import java.util.HashMap;
import java.util.Iterator;
public final class FinalClassExample {
private final int id;
private final String name;
private final HashMap<String,String> testMap;
public int getId() {
return id;
}
public String getName() {
return name;
}
/**
* Accessor function for mutable objects
*/
public HashMap<String, String> getTestMap() {
//return testMap;
return (HashMap<String, String>) testMap.clone();
}
/**
* Constructor performing Deep
* @param i
* @param n
* @param hm
*/
public FinalClassExample(int i, String n, HashMap<String,String> hm){
System.out.println("Performing Deep for Object initialization");
this.id=i;
this.name=n;
HashMap<String,String> tempMap=new HashMap<String,String>();
String key;
Iterator<String> it = hm.keySet().iterator();
while(it.hasNext()){
key=it.next();
tempMap.put(key, hm.get(key));
}
this.testMap=tempMap;
}
/**
* Constructor performing Shallow
* @param i
* @param n
* @param hm
*/
/**
public FinalClassExample(int i, String n, HashMap<String,String> hm){
System.out.println("Performing Shallow for Object initialization");
this.id=i;
this.name=n;
this.testMap=hm;
}
*/
/**
* To test the consequences of Shallow and how to avoid it with Deep for creating immutable classes
* @param args
*/
public static void main(String[] args) {
HashMap<String, String> h1 = new HashMap<String,String>();
h1.put("1", "first");
h1.put("2", "second");
String s = "original";
int i=10;
FinalClassExample ce = new FinalClassExample(i,s,h1);
//Lets see whether its copy by field or reference
System.out.println(s==ce.getName());
System.out.println(h1 == ce.getTestMap());
//print the ce values
System.out.println("ce id:"+ce.getId());
System.out.println("ce name:"+ce.getName());
System.out.println("ce testMap:"+ce.getTestMap());
//change the local variable values
i=20;
s="modified";
h1.put("3", "third");
//print the values again
System.out.println("ce id after local variable change:"+ce.getId());
System.out.println("ce name after local variable change:"+ce.getName());
System.out.println("ce testMap after local variable change:"+ce.getTestMap());
HashMap<String, String> hmTest = ce.getTestMap();
hmTest.put("4", "new");
System.out.println("ce testMap after changing variable from accessor methods:"+ce.getTestMap());
}
}
浙公网安备 33010602011771号