Java裡的 String,看似簡單,但大有學問

Java裡的 String,看似簡單,但大有學問

String 為什麼用 final 修飾?

在進入 class 學習後,我們不僅會接觸到 String,還會接觸到包裝類。什麼是包裝類呢?String 和 包裝類都有一個共同點。

1、包裝類

Java 中的基本數據類型沒有方法和屬性,而包裝類就是為了讓這些擁有方法和屬性,實現對象化交互。

Java裡的 String,看似簡單,但大有學問

基本數據類型

Java裡的 String,看似簡單,但大有學問

包裝類

2、包裝類和 String 類為什麼都用 final 修飾?

① 源碼

Java裡的 String,看似簡單,但大有學問

String

Java裡的 String,看似簡單,但大有學問

Integer

② 為什麼 String 要設計成 final?

我們都知道 String 類的不可變型。用 final 修飾意味著不可繼承和修改。當一個 String 變量被第二次賦值時,不是在原有內存地址上修改數據,而是在內存中重新開闢一塊內存地址,並指向新地址。

Java裡的 String,看似簡單,但大有學問

設計成 final 的好處:

(1)不可變性支持線程安全

(2)不可變性支持字符串常量池,提升性能

(3)String 經常在 Map 中作為 key 值,保證 HashCode 的不可變性。

你是否弄懂了 String?小試牛刀一下

Java裡的 String,看似簡單,但大有學問

圖1

輸出結果:

見評論區,測測你和其他人的答案是否一樣

聊聊圖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、測試

Java裡的 String,看似簡單,但大有學問

輸出結果:999

很明顯,輸出的結果和我們預期的不一致。

如果這個時候,面試官問你,StringBuild 什麼地方會導致線程不安全?

① 我們定位到 appen 方法

Java裡的 String,看似簡單,但大有學問

我們看第 450 行, count += len ,這不是原子操作

Java裡的 String,看似簡單,但大有學問

如果多線程下,這個 count 值 必然出現問題

| 文

如果你還遇到其他的 String 相關的面試題,歡迎分享評論區,咱一起盤盤。


分享到:


相關文章: