我們都知道,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
s1
及s2
都是直接用雙引號的方式來宣告,又稱為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",與s1
及s2
的記憶體位址並不相同,所以s1 == s3
結果為false。
s4
是s3
呼叫intern()
方法取得的值,該方法是拿s3
指向的內容"hello world",去String Pool找是否有相同的內容,若有則回傳String Pool該字的記憶體位址,也就是與s1
及s2
指向的同一個位址,所以s1 == s4
為true。
沒有留言:
張貼留言