有關string的那些事
阿新 • • 發佈:2021-09-28
1
)String類是
final
類,也即意味著String類不能被繼承,並且它的成員方法都預設為
final
方法。在Java中,被
final
修飾的類是不允許被繼承的,並且該類中的成員方法都預設為
final
方法。
2
)String類底層是
char
陣列來儲存字串的。
對String物件的任何改變都不影響到原物件,相關的任何change操作都會生成新的物件
字串常量池
在
class
檔案中有一部分來儲存編譯期間生成的字面常量以及符號引用,這部分叫做
class
檔案常量池,在執行期間對應著方法區的執行時常量池。
JVM為了減少字串物件的重複建立,其維護了一個特殊的記憶體,這段記憶體被成為字串常量池或者字串字面量池
工作原理
當代碼中出現字面量形式建立字串物件時,JVM首先會對這個字面量進行檢查,如果字串常量池中存在相同內容的字串物件的引用,則將這個引用返回,否則新的字串物件被建立,然後將這個引用放入字串常量池,並返回該引用。
實現前提
字串常量池實現的前提條件就是Java中String物件是不可變的,這樣可以安全保證多個變數共享同一個物件。如果Java中的String物件可變的話,一個引用操作改變了物件的值,那麼其他的變數也會受到影響,顯然這樣是不合理的。
String str1 =
"hello"
;
這裡的str1指的是方法區中的字串常量池中的“hello”,編譯時期就知道的;
String str2 =
"he"
+
new
String(
"llo"
);
這裡的str2必須在執行時才知道str2是什麼,所以它是指向的是堆裡定義的字串“hello”,所以這兩個引用是不一樣的。
如果用str1.equal(str2),那麼返回的是
true
;因為String類重寫了equals()方法。
編譯器沒那麼智慧,它不知道
"he"
+
new
String(
"llo"
)的內容是什麼,所以才不敢貿然把
"hello"
這個物件的引用賦給str2.
如果語句改為:
"he"
+
"llo"
這樣就是
true
了。
new
String(
"zz"
)實際上建立了
2
個String物件,就是使用“zz”通過雙引號建立的(在字串常量池),另一個是通過
new
建立的(在堆裡)。只不過他們的建立的時期不同,一個是編譯期,一個是執行期。
String s =
"a"
+
"b"
+
"c"
;
語句中,“a”,
"b"
,
"c"
都是常量,編譯時就直接儲存他們的字面值,而不是他們的引用,在編譯時就直接將它們連線的結果提取出來變成
"abc"
了。