使可變性最小化(15)

一、java語言支持四種類型:java

(1)接口(interface):數組

(2)類(class):緩存

(3)數組(Array):安全

(4)基本類型(primitive):惟一非引用類型(reference type)多線程

二、方法簽名:包括方法名稱、參數,不包括返回值;併發

《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《函數

三、不可變類性能

  • 實例不可被修改類
  • 每一個實例中包含的全部信息,必須在建立的時候提供,並在整個生命週期不可變
  • 例如:String、基本類型包裝類、BigInteger、BigDecimal
  • 比可變類,易於設計使用,不易出錯、更加安全

四、成爲不可變類,五條規則ui

(1)不提供任何修改對象狀態的方法線程

(2)保證類不會被擴展

  • 這樣能夠防止粗心、惡意子類,僞裝對象狀態已經改變;
  • 防子類化,通常使用 final 類

(3)全部的類都是 final 

  • 經過系統的強制,代表意圖

(3.1)不可變類變成 final 的另外一種作法:

  • 使不可變類全部構造方法都變成私有或包級私有,添加公有靜態工廠,替換公有構造器

(4)全部域都私有

  • 技術上容許不可變類具備公有 final 域(域包含基本類型值或 不可變對象引用)
  • 不建議上述作法緣由:之後版本沒法改變內部表示法

(5)確保對任何可變組件的互斥訪問

  • 若是類具備可變對象的域,須保證客戶端沒法或者這些對象的引用
  • 不要用客戶端提供的對象引用初始化 可變對象的域
  • 不要從任何訪問方法返回該對象引用
  • 在構造器、訪問方法、readObject方法(76條)中,請使用保護性拷貝(39條)

五、函數方式的模式

  • 對操做數進行運算,但不修改,返回新建立的實例
  • 大多數不可變類都是用該模式
  • 該作法帶來了不可變性
  • 約束關係在整個生命週期都不變,不須要額外代碼維護約束關係

六、不可變對象本質上是線程安全的,且不要求線程同步

  • 多線程併發訪問不可變類對象,不會破壞對象,線程安全最容易實現
  • 不可變對象能夠被自由的共享
  • 鼓勵客戶端儘量重用現有實例(簡單實現:頻繁用到的值,提供公有靜態 final 常量)
  • 對不可變類提供靜態工廠<1條>,緩存公用頻繁使用的實例
  • 基本類型包裝類、BigDecimal等就有這樣靜態工廠
  • 使用靜態工廠而不是公有構造器,之後添加緩存更靈活

七、不可變對象能夠被自由的共享

  • 永遠不須要進行保護性拷貝<39條>
  • 不該該對不可變類提供 clone 方法或 拷貝構造器<11條>
  • String類有拷貝構造器,儘可能不要使用<5條>

八、不只能夠共享不可變對象,能夠共享內部信息

  • 不可變類BigInteger,在使用negate()得到相反數時,內部mag指向原有對象的mag數組
  • 由於是不可變類,對象不會被修改才能夠這麼操做

九、不可變對象真正缺點

  • 對於每個單獨的值都須要一個單獨的對象;
  • 好比:一個百萬位的BigInteger,運算時須要不停建立新對象,性能消耗巨大;
  • BitSet 則容許固定時間內,改變某一位

十、若是不可預測,提供公有可變嵌套

  • String類的可變公有嵌套:StringBuild(和已經基本廢止的StringBuffer)

十一、若是可預測,能夠採用內部可變對象,存取中間值

  • 這樣,不用每一步都建立不可變對象

十二、BigInteger和BigDecimal剛北邊寫出來時,不可變類必須是 final 未獲得普遍認同

  • 這倆類,存在被繼承和被篡改的風險

1三、不可變類沒有方法會修改對象,全部域必須是 final

  • 爲提升性能能夠有非 final 的域:第一次運算時將開銷昂貴的結果保存起來,下次直接用
  • 不可變性,保證告終果的正確性

1四、序列化功能一條告誡:

  • 不可變類實現了Serializable接口,須要顯式readObject等4個方法
  • 攻擊者可能從不可變類建立可變對象<76條>

1五、沒有好的理由,類就要作成不可變得

1六、類不能作成不可變的,也要儘可能限制其可變性;

1七、除非有好的理由,每一個域都應該是 final 的

1八、構造器和靜態工廠外,不該再提供公有初始化方法

1九、不可變類不要提供從新初始化方法

相關文章
相關標籤/搜索