# 虎年行大運 ~ Java Foundamental 系列 - Immutable Object ## 【前言】 你不常聽到這個詞,但你一定常常在使用例如 String 等物件,而 String 正是一種 Immutable Object - 為什麼有這種類? - 為什麼需要這種類? - 使用在系統內有什麼好處? 文中將會逐步介紹,並給出解釋 ## 【介紹】 **Immutable Object** 如同字面上意義 -- **是不可變更類**,他不是一個固定的類或 Interface,而是一種概念,任何符合這種設計概念的類都可以稱做是 Immutable Object,諸如上述提到的 String 我們都知道在建立 String 物件的時候,實際上就是直接建了一個值在 Stack 內,後續的修正行為都只是重新建立新的值並做拆組動作。 ```java= String str = "1"; // 建立一個值為 1 的 String 物件 str = "2"; // 建立一個值為 2 的 String 物件 str = str + "3"; // 建立一個值為 3 的 String 物件,再建一個值為 23 的組合後的新 String 物件 ``` 看完上述的底層操作之後,要明白為何推薦字串的處理都是使用 StringBuilder(非同步)、StringBuffer(同步) 而什麼是 Immutable Object 的概念呢? - **屬性設置為 Private** - **屬性設置為 Final** - **不提供修正屬性的方法** - **屬性非基本類型時,使用 COPY 方式給出新物件,不是直接給索引** - **覆寫 equals() 和 hashCode() 方法** ### 屬性設置為 Private / 屬性設置為 Final 作為 Immutable Object,最重要的便是不讓任何物件中任何屬性被恣意拿取和修改,因此在建立物件的初期,便需要針對所有的屬性進行 final 的宣告。 ### 不提供修正屬性的方法 承上,若你無法保證屬性的 final 宣告,可能是因為一些業務邏輯需要做到內部的變化處理 (通常不可能),那至少不能提供可以修正屬性的方法,避免屬性被外部的操作變更值 ### 屬性非基本類型時,使用 COPY 方式給出新物件,不是直接給索引 舉例: 如果屬性為集合類物件,那外部就可以在取得物件之後,設法修改裡面的值,如此一來 Immutable Object 的集合屬性內的值就會因此被改變 為避免這種狀況發生,必須要在這類型物件的 Getter() 方法去執行 Copy 的動作,複製出一個新物件送回給外部使用,避免原始物件來源被改變 ### 覆寫 equals() 和 hashCode() 方法 在上一篇 Foundametal 的文章內有提到,正確進行 equals() 和 hashCode() 的覆寫可以讓其在 HashMap, HashSet, HashTable 等集合類的處理上避免重複的可能性。 更甚是,為了讓 Immutable Object 實現其意義上的獨一無二,必定會進行這兩方法的覆寫,實現盡可能接近百分百的防止重複。 ## 【優缺點】 優點: - 確定物件的不再變動特性,因此取用上不需要顧慮是否要複製的問題,直接取用索引來源即可 - 非常適合多執行緒的環境 缺點: - 由於新的改變就會建立新的 Immutable Object,因此不免會造成無用物件堆積,這些都需要在過程中額外處理,算是比較費工的一點 ## 【結語】 在追求更快速產出的環境中,適當的針對一經建立便不再變動的資料做 Immutable Object (Data Bean) 的處理,不再需要確認資料的狀態情況下,會提升流程的效率。 首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA) ###### tags: `Java Foundament`