1. 程式人生 > 其它 >Java漫談11

Java漫談11

這次我們接著聊String,這次我們聊聊String類為什麼是final的。

之所以聊這個,是因為在知乎上看了一篇帖子,看完後讓我對這個點有了認識,在這裡跟你分享分享我的理解。

點選原文給你看這篇帖子。

總結來說,String之所以設計成final,是為了資料安全。

因為String不是8大基本的資料型別,所以String的值其實存的是一個記憶體地址,在這個地址就相當於儲存值的那個倉庫的編號。例如:

String a = "hello world";

這之中,a的實際值並不是hello world,而是類似於0x0045這樣的記憶體地址值。因此,假設一種場景,假設String並不是final。此時,新定義一個變數b,並將變數a賦值給b。邏輯上是變數a將值賦給了變數b,可實際上是變數a將剛才提到的代表記憶體地址的“門牌號”賦值了了b。此時,如果我們要是修改b的值(變成“hello world-b”),其實,a的值也會一併修改。

而這樣就與我之前的想要的邏輯結果不一致了,因為我只是僅僅想要b的值變成“hello world-b”,而a的值仍然保持“hello world”不變。

好,現在我們來看看在final修飾的場景下,String的結果又會怎樣。注意,此時我們重新定義一下String的修飾場景,即String是有final修飾,但String並未啟用常量池。同樣是b複製了a的地址,b修改值,也就是b按照門牌號碼找到倉庫,去倉庫裡修改商品去了。所以b修改完之後,當a再順著地址值(門牌號碼)去提取商品資訊的時候,發現商品也變了。

咦……這還是不對啊,實際當中的String遇到這種情況,結果是b變,a不變的呀。難道是常量池的作用,不對,常量池只是保證了讀取速度的提高,而不會對值進行改變。如此一來,一個比較靠譜的解釋就如文章中@胖胖所說:

所以 String 是不可變,關鍵是因為 SUN 公司的工程師,在後面所有 String 的方法裡很小心的沒有去動 Array 裡的元素,沒有暴露內部成員欄位。

好了,邏輯分析完了,我想說說我自己弄清這些這個邏輯之後的感受。Java的String這個類是我在一開始學習的時候遇到的,起初一直把它誤認為是一個基本的資料型別,以為它就是很簡單的一個底層的實現。聊了這兩期漫談之後,才發現,在它平淡的外表下,原來隱藏著一個比較深的邏輯設計迴路。而這個迴路也正是工程師構造資料型別,封裝資料功力的體現。

而這樣的功力讓我想到了一個詞——靜水流深。意思是通過表面平靜的水並不知道水底有多深,來暗喻表面不聲不響的人卻藏著大智慧。我想這個詞即適用於String這個類,也適用於構造String這個類的那些工程師們。

向String這個類,向構造這些類的工程師們致敬。願你我有一天也能踏入這層境界。

清 單

  1. String的final主要的作用是保證了資料的安全。
  2. 表面上看它的資料安全來源於final的不可變性,實際上是來源於String類底層的封裝。