記憶體有兩個區塊,一個叫做 stack, 一個叫做 heap。 當我們宣告一個字串 String str = "123"; 時, 程式就會把 str 名稱記在 stack 裡面,再把 123 這個值記在 heap 裡面。 然後將 str 跟 123 做一個關聯性的參考。 (當然實際上是更複雜的,這邊先簡化敘述讓你比較好理解) 因此我們印出 str 時,程式就會參照這個關聯將 123 印出來。  但若我們想要覆蓋過去原本的值時,像以下這樣的例子。 str = str + "abc"; 這個時候我們 str 就會指向新的位置,其值就會變成 123abc 了。 記憶體的變化會像是這樣的狀態。  這個時候可能會有疑問,被取消關聯的 123 會怎麼樣? 當程式中沒有任何參考(reference)指向他的話, 這個放置著 123 的 heap 記憶體位置,就會被當成垃圾, 當 Java 執行垃圾回收(Garbage Collection)時,這塊記憶體就會釋放掉。 這就是字串串接時,記憶體部分會產生的動作。 也由於字串是常數的關係,所以任何會改變內容的行為(串接、取代、刪除等), 在記憶體之中都是以類似方法操作物件。 --- 然後假設有一個狀況是這樣, ```java public static void main(String[] args) { String str = ""; for (int i = 0; i < 10; i ++) { str = str + i; } System.out.println(str); //會印出 0123456789 } ``` 那麼記憶體的變動就大概如以下圖片這樣子的。  這個時候可以看見其實 heap 會有很多沒有被參考到的記憶體位置存在, 需要等到 Java 的垃圾回收(GC)後才會釋放這些記憶體。 但其實 GC 是由程式控管,我們無法主動呼叫 GC,也沒辦法得知 GC 何時會發生。 且 GC 發生時也會稍稍的影響程式的運作效能。 所以一般來說,如果有大量的字串需要用拼湊的方式建立的話, 其實不建議直接操作字串,因為程式會產生大量待回收的垃圾。 ```java public static void main(String[] args) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10; i ++) { sb.append(i); } System.out.println(sb.toString()); //會印出 0123456789 } ``` 所以,如果真的有需要拼湊字串的需求時, 我們會建議使用 StringBuilder 或者 StringBuffer 之類的物件, 當我們想要操作字串內容時, 這些程式的做法是,會先將拼湊的字串內容置於一個緩衝區之內, 等到全部拼湊完且將其轉換成字串後,才真正的會將這個字串置於 heap 內。 像這樣的做法就不容易產生大量的垃圾了。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up