學習effective java-15類和接口之使可變性減少

 

該知識點是自己從書籍中學習的筆記。

 

 不可變類是一個其類實例不能夠被修改的簡單類。Java平臺提供了很多不可變類:String、裝箱好的原始數據類型、BigInteger、BigDecimal。使用不可變類是更安全的。爲了使一個類成爲不可變類,需要以下幾個條:

a.       不提供任何修改該對象狀態的方法。

b.       確保該類不能夠繼承,在該類上加final即可。這樣可以防止通過子類來修改類的狀態。

c.       確保所有屬性都是final的。

d.       確保所有的屬性都是private的。

e.       對於任何可變組件,確保都是互斥訪問的。如果你的類中含有指向對象的引用,請確保該類的客戶不能夠獲取這些指向對象的引用。不能夠通過訪問器將類中的屬性由客戶提供的對象引用來初始化或者返回一個對象引用。

不可變對象的優點:

a.       不可變對象可以很好的使用,它只有一個狀態,就是在創建的時候;

b.       不可變對象是線程安全的,不要求同步。使用不可變對象可以創建一些經常被訪問的對象。比如說可以在類中加上public static final A a = new A(“W”);同時可以將一些經常訪問的對象緩存起來。

c.       不可變對象不僅可以被共享,並且其內部結構信息也可以被共享;

d.       不可變對象還爲其他對象,無論是可變還是不可變對象,都提供了大量的構件。

不可變類的缺點:

對於每一個值,不可類都要創建一個單獨的對象。如果這個值是比較大的話,那麼創建成本會增加。比如說,你想要一個一百萬位的BigInteger,但是僅僅想修改最低位的值,代碼如下:

BigInteger moby = ...;

moby = moby.flipBit(0);//flipBit會返回一個BigInteger的實例,但是僅僅最低位,那麼就會浪費很多空間和時間。在這個時候你可以使用BitSet(BitSet是可變對象),因爲它中的位是沒有順序的,在同一個時間可以任意修改。

如果使用不可變類,其性能會下降的話,可以使用和它配套的可變類,比如說String有StringBuffer,BigInteger有BitSet。

要使類成爲不可變類,除了將class聲明爲final外,同時可以還可以將class的構造方法聲明爲private,讓子類不能夠繼承,或者再提供一個靜態工廠方法(構造方法都是新生成一個新對象;如果靜態工廠方法可以接受一個參數,那麼最好是判斷其參數的class是否與生成的對象的class是否一致,如getClass())。

總的來說,你應該儘量將類設計成不可變類,雖然在性能上有些缺點。將類設計成不可變類的同時,請提供個與該類功能基本相同的配套的可變類,防止今後要提高性能的時候可以優選它。

對於一些類將其設計成不可變類是不合理的,比如說Thread、TimerTask,這樣的過程類。對象的所有初始化工作應該儘量在構造方法中完成,而不應該完成了一部分工作,然後交由其他方法來完成。這樣會造成對象的不一致性,除非有足夠的理由不得不這樣做。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章