Java基礎知識:String爲什麼是不可變類型?

String

String是不可變類型。這裏的不可變是指,當編譯器開闢堆內存來存儲String內容後,這個堆內存無法再被外界修改。

但是,程序員可以創建一個String類型變量,通過賦值的方式,使之指向不同的堆內存,從而產生String字符串可變的假象。

由於String字符串的不可變性,就導致拼接、提取字符串的過程中,需要創建新的堆內存來存放結果,這和直接修改堆內存相比要低效的多。

但是Java語言的設計者爲什麼要這麼做呢?

  1. 不可變字符串有一個優點:編譯器可以讓字符串共享。也就是說相同內容的字符串,其實是共享同一個堆內存的,不管你創建多少個,只要字符串內容一樣,其幕後都指向一個堆內存。
// 不信,你試試
String s1 = "Hello World!";
String s2 = "Hello World!";
//注意:判斷兩個字符串是否指向同一個內存地址,需要使用‘==’,使用equal是判斷兩個字符串內容是否相等,注意這兩個概念的區別!
System.out.println(s2 == s1);
//你會發現打印結果是:true

字符串共享機制,會使得字符串比較變得非常簡單,因爲指向同一個堆內存地址的字符串肯定是相等的,而不需要挨個遍歷字符。(P.S. 當然了,如果兩個字符串並非指向同一個地址,則還是需要比對字符串內容)

注意!!!判斷兩個字符串是否相等,一定要使用 s1.equals.(s2),而不能直接使用s1 == s2,否則你會遇到很奇怪的調試現象,別怪我沒提醒你 -_-||

  1. 字符串其實很少被修改。翻翻代碼你就會發現這個結論。不過,話說回來,如果我真想就像頻繁改動字符串,該怎麼辦呢?Java推薦你使用StringBuilder

這就是爲什麼,簡單拼接字符串時,你可以優雅地使用字符串拼接符+;當頻繁構建字符串時,拼接符+的低效性就暴露出來,StringBuilder雖然難看,但很高效。優雅和高效,二者難以兼得。

final

final關鍵字是用來控制變量初始化後的對象引用不會再指向其他對象。
String本身是一個不可變的類,指的是不可修改String對象的內容。

如果要確保String類型變量定義之後,永不可變(不可再指向其他堆內存),可以使用final修飾之。

//我們既沒辦法修改s指向的堆內存的內容,也無法將新的String對象賦值給s.
//因此s永不可變。
private final String s = "Hello World!";

final也可以用來修飾可變類,例如StringBuilder:

private final StringBuilder sb;
sb = new StringBuilder();

//雖然使用final修飾StringBuilder,由於StringBuilder屬於可變類,
//因此我們依然可以通過append方法修改sb對象所指向的堆內存的內容。
//但是我們無法重新讓sb指向一個新的StringBuilder對象引用。
sb.append("abcd");//正常
sb.append("1234");//正常
sb = new StringBuilder();//無法執行
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章