我們知道字元有兩種初始化方式: String s1 = “abc”; String s2 = new String("def"); 這兩種有什麼區別呢?這時就需要我們看看String的在記憶體中是怎麼存儲的了。我們先看下麵的圖瞭解其在記憶體在是怎麼存儲的: 首先是 String s1 = “abc”;它 ...
我們知道字元有兩種初始化方式:
String s1 = “abc”;
String s2 = new String("def");
這兩種有什麼區別呢?這時就需要我們看看String的在記憶體中是怎麼存儲的了。我們先看下麵的圖瞭解其在記憶體在是怎麼存儲的:
首先是 String s1 = “abc”;它首先會去常量池去檢查是否存在“abc“,如果存在就返回,否則就創建。“abc”的地址給了s1,s1指向了它。而String s2 = new String("def");它會先去堆記憶體中去創建一個new String()對象,然後去常量池檢查是否存在"def" 如果存在就返回,否則創建。“def”的地址給了new String(),而new String()自給有一個地址給了s2。這就是字元串的基本存儲過程。
接下來我們看看字元串的一個重要特性:字元串是常量,它們的值在創建之後不能更改。
如下麵一段代碼
public class TestString { public static void main(String[] args) { String s = "abc"; s+="def"; System.out.println(s); } }
根據上面的分析我們可以知道 s 最開始是指向"abc",後面 s+="def"做個一個字元串拼接,而在記憶體中並沒有直接把"def”拼接在“abc”上,而是先開闢了空間存儲“def”,最後把abcdef拼接在一起,開闢了第三塊空間。通過這個例子我們可以知道不能變的是字元串的值,即“abc”不能改變,而引用是可以改變的。所以最後 s列印出來的值變了,並不是“abc”發生了變化,而是s指向了新的對象“abcdef”。
接下來我們可以通過1個例子看看
public class TestString { public static void main(String[] args) { String s1 = "abc";
String s2 = "abc" String s3 = new String("abc");
System.out.println(s1==s2) System.out.println(s1==s3); System.out.println(s1.equals(s3)); } }
首先我們要知道==和equals的區別,==比較的是地址,而equals預設比較也是地址,而String重寫了equals()方法,比較的是值是否相同。根據上面的理解我們畫出記憶體圖
根據上圖我們知道了 String s1 = "abc";首先會在常量池中創建“abc”,s1指向此對象,而 String s2 = "abc"首先會在常量池中檢查發現存在“abc”,所以s2並不會再創建而是直接指向“abc”,而 String s3 = new String("abc");首先會在堆記憶體new 一個String對象,然後指向常量池中已經存在的“abc” (不會再創建“abc”),但是new String()給s3是自己的地址,並不是“abc”的地址。所以輸出結果為true false true
現在拋出一個問題 String s = “abc”和 String s = new String("abc")有什麼區別?
答案詳情請見下一篇隨筆