網頁

2019/6/1

Java String Pool 字串池,使用 == 比較兩個String是否相等

我們都知道,Java程式中比較兩個String變數是否相同時,應該用equals(String s),但面試時常會看到使用==比較兩個String變數,這主要是考你是否知道String Pool(字串池)的概念。

String Pool存放在Java Heap區的記憶體位置。

請觀察以下。

String s1 = "hello world";
String s2 = "hello world";
String s3 = new String("hello world");
String s4 = s3.intern();

System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s3 == s4); // false
System.out.println(s1 == s4); // true

System.out.println(s1.equals(s3)); // true
System.out.println(s3.equals(s4)); // true

System.out.println(System.identityHashCode(s1)); // 739498517
System.out.println(System.identityHashCode(s2)); // 739498517
System.out.println(System.identityHashCode(s3)); // 125130493
System.out.println(System.identityHashCode(s4)); // 739498517

s1s2都是直接用雙引號的方式來宣告,又稱為String Literals。JVM在編譯時看到這樣的宣告會去String Pool裡找是否有同樣的字,沒有的話會將字存入String Pool,若有的話則將儲存字的位址返回。

宣告s1時String Pool裡面沒有任何字,所以JVM會在String Pool的記憶體生一塊位置來存放"hello world",然後將位址返回給s1
宣告s2時,JVM會先拿宣告的"hello world"去String Pool中看是否有存在相同的字,因為s1之前已經宣告過,所以JVM會將s1宣告的"hello world"記憶體位址返回給s2

這也是為什麼s1 == s2為true的原因,因為兩個字串變數的值實際上都是指向同個記憶體位置的值。


s3是用new關鍵字產生了一個String Pool外的新的記憶體位置來存放"hello world",與s1s2的記憶體位址並不相同,所以s1 == s3結果為false。

s4s3呼叫intern()方法取得的值,該方法是拿s3指向的內容"hello world",去String Pool找是否有相同的內容,若有則回傳String Pool該字的記憶體位址,也就是與s1s2指向的同一個位址,所以s1 == s4為true。


沒有留言:

張貼留言