物件的建立,許多新手也都耳熟能詳了,例如
public class school
但是因為private關鍵字的作用,其他類無法直接訪問person物件,所以產生了「發布」物件概念。物件的「發布」指的是「使物件能夠在當前作用域之外的**使用」。改變private關鍵字就可以達到目的:
public class school
也有延遲建立方法,這樣只有在呼叫init()函式時才例項化person物件,相對來說更為優質:
public class school
}
模擬物件導向的封裝特性,可以說「封裝」是一種更加嚴格規範的「發布」。
物件發布、建立最容易犯的錯誤就是物件逸出,「物件逸出」指的是某不應該發布的物件被發布的情況。
例如school類引用了person類,但是假若要求不該讓外界知道person物件的具體內容,那麼之前的操作都不應該進行。但是時常發生的是:你認為已經封裝好了物件,但是不經意的操作仍然造成了「物件逸出」。根據形式不同可以分為「顯式逸出」和「隱式逸出」。
顯式逸出
顯示逸出主要問題在於向外界暴露了物件的引用。比如向外發布乙個陣列,很多人會選擇這麼做:
public class school ;
public person getpersonarray()
}
這麼發布person陣列並不安全,因為呼叫getpersonarray()函式的地方會持有personarray在堆記憶體中的引用,可以間接暴露、改變原personarray中的元素。
所以假若你只是想定義乙個陣列,只想讓外界讀取陣列元素,不能改寫陣列,getpersonarray()向外界返回的應該只是personarray陣列的乙個副本。
public class school ;
public person getpersonarray()
}
要格外注意新手最容易犯的錯,person personarrayerror = personarray並不是得到了複製陣列,而是在棧中產生了乙個新的personarrayerror變數儲存person陣列在堆中位址的引用。這是personarrayerror語句執行的示意圖:
顯式逸出還有一種情況:乙個私有的物件新增到乙個集合中去,其他類仍可以通過遍歷集合(visitlist)獲得該物件:
public class school
}
隱式逸出隱式逸出主要問題在於新建其他物件時候暴露了this引用,例如:
public class school
}
這裡造成了this引用在建構函式逸出。因為在person物件發布(例項化)的同時,也間接發布了this應用。這樣school類的建構函式還未結束,就發布了乙個尚未構造完成的school物件。單執行緒執行問題不大, 多執行緒要考慮競態條件(執行緒執行時序),因而這是一種不安全的物件構造過程。
該如何規避呢?多看看一些別人的工程**後,你就容易得到你的答案:
public class school
private synchronized void initparam()
}
首先,initparam()函式用了synchronized互斥鎖,意味著同一時刻只能有乙個執行緒來例項化person和room物件。
再者,呼叫initparam(),未到達方法出口,不會提前暴露this引用,也就不會造成未構造完成的school物件被提前發布了。
併發程式設計 08安全發布物件之發布與逸出
小結 發布物件 使乙個物件能夠被當前範圍之外的 所使用,日常開發中比較常見的比如通過類的非私有方法返回物件的引用,或者通過公有的靜態變數發布物件等都屬於發布物件 物件逸出 首先需要明確的是物件逸出是一種錯誤的發布方式。當乙個物件還沒有構造完成時,就使它被其他執行緒所見。package com.art...
併發程式設計 發布與逸出
發布 物件能在當前作用域之外的 中使用。發布方式 1 物件引用儲存到其他地方 2 public方法返回物件引用 3 引用傳遞到其他方法 某個不該發布的物件發布,這種情況成為逸出 封裝使得程式的正確性進行分析變得可能,這也是封裝最重要的意圖,構造物件的過程中不要讓this引用逸出,常見的是在建構函式中...
物件的共享(一) 發布和逸出
發布 publish 乙個物件的意思是,是物件能夠在當前作用域之外的 中使用。例如,將乙個指向該物件的引用儲存到其他 可以訪問的地方,或者是在某乙個非私有的方法中返回該物件的引用,或者將物件的引用傳遞到其他類的方法中。逸出 escape 當某個不應該發布的物件被發布時。上面的定義比較抽象,下面看乙個...