String 為什麼用 final 修飾?
在進入 class 學習後,我們不僅會接觸到 String,還會接觸到包裝類。什麼是包裝類呢?String 和 包裝類都有一個共同點。
1、包裝類
Java 中的基本數據類型沒有方法和屬性,而包裝類就是為了讓這些擁有方法和屬性,實現對象化交互。
2、包裝類和 String 類為什麼都用 final 修飾?
① 源碼
② 為什麼 String 要設計成 final?
我們都知道 String 類的不可變型。用 final 修飾意味著不可繼承和修改。當一個 String 變量被第二次賦值時,不是在原有內存地址上修改數據,而是在內存中重新開闢一塊內存地址,並指向新地址。
設計成 final 的好處:
(1)不可變性支持線程安全
(2)不可變性支持字符串常量池,提升性能
(3)String 經常在 Map 中作為 key 值,保證 HashCode 的不可變性。
你是否弄懂了 String?小試牛刀一下
輸出結果:
見評論區,測測你和其他人的答案是否一樣
聊聊圖1中的情況 3
採用 new 關鍵字新建一個字符串對象時,JVM 首先在字符串池中查找有沒有 "abc" 這個字符串對象,如果有,則不在池中再去創建 "abc" 這個對象了,直接在堆中創建一個 "abc" 字符串對象,然後將堆中的這個 "abc" 對象的地址返回賦給引用 s5,這樣,s5 就指向了堆中創建的這個 "abc" 字符串對象;如果沒有,則首先在字符串池中創建一個 "abc" 字符串對象,然後再在堆中創建一個 "abc" 字符串對象,然後將堆中這個 "abc" 字符串對象的地址返回賦給 s5 引用,這樣,s5指向了堆中創建的這個 "abc" 字符串對象。s6 則指向了堆中創建的另一個 "abc" 字符串對象。s5 、s6 是兩個指向不同對象的引用,結果當然是 false。
如果你覺得很繞,說明你 Java 基礎這塊有待提高。
情況 5
雖然 s11 和 s12 各自指的是常量池裡面 "a","b" 的引用,但是 String 在做加法或者 subString、replace 等方法的時候,實際上返回的是 new String () 的結果,因此 str 指向的是堆中的地址,所以不相等。
情況 6
雖然此處 ss 是 new 出來的新對象,但是由於調用了 intern 方法,這個方法會返回常量池中相等值的字符串的地址,所以最後 ss 指向的是常量池中 "abc" 的地址,所以相等。
String、StringBuffer 和 StringBuild
1、String 不可變字符序列,如果要操作少量的數據用 String;
2、StringBuffer 可變字符序列、效率低和線程安全,多線程操作字符串緩衝區下操作大量數據用 StringBuffer
StringBuffer 中的方法大都採用了 synchronized 關鍵字進行修飾
3、StringBuild 可變字符序列,效率高和線程不安全,單線程操作字符串緩衝區下操作大量數據用StringBuilder
為什麼說 StringBuild 是線程不安全?
1、測試
輸出結果:999
很明顯,輸出的結果和我們預期的不一致。
如果這個時候,面試官問你,StringBuild 什麼地方會導致線程不安全?
① 我們定位到 appen 方法
我們看第 450 行, count += len ,這不是原子操作
如果多線程下,這個 count 值 必然出現問題
| 文
如果你還遇到其他的 String 相關的面試題,歡迎分享評論區,咱一起盤盤。
閱讀更多 Python大星 的文章