什麼是釋出對象——使對象在目前作用域之外的代碼中使用
什麼是逸出——當某個不應該釋出的對象被釋出時
對象如何逸出的
- 最簡單的方法是将對象的引用儲存到一個公有的靜态變量中
- 當釋出某個對象時,可能會間接地釋出其他對象。如果将一個對象添加到被釋出的集合對象中,那麼同樣會釋出這個對象
- 當釋出一個對象時,在該對象的非私有域中引用的所有對象同樣會被釋出;或者說當把一個對象傳遞給某個外部方法時,就相當于釋出了這個對象
- 不安全的對象構造過程:指this引用在構造函數中逸出
- 常見的錯誤做法1是,在構造函數中啟動一個線程,this引用就被新建立的線程共享了
- 常見的錯誤做法2是,在構造函數中注冊一個事件監聽器,this引用就被觸發被監聽事件的線程共享了
- 解決辦法是:使用一個私有的構造函數和一個公共的工廠方法,看下面的例子
public class SafeListener { private final EventListener listener; private SafeListener() { listener = new EventListener() { public void onEvent(Event e) { doSomething(e); } }; } public static SafeListener newInstance(EventSource source) { //隻有當構造函數傳回時,this引用才應該從線程中逸出 SafeListener safe = new SafeListener(); source.registerListener(safe.listener); return safe; } }
注意:隻有當對象的構造函數傳回時,對象才處于可預測和一緻的狀态。是以,當從對象的構造函數中釋出對象時,隻是釋出了一個尚未構造完成的對象,即使釋出對象的語句在最後一行也是如此,如果this在構造過程中逸出,那麼這種對象就被認為是不正确的構造