Java基礎: 由 intern 看 String

來源:互聯網
上載者:User

String這個類,是Java中很經典的類,從我們學Java的那天起就與他結下“梁子”,在以後的日子他更是如影隨形,對你不離不棄。所以,瞭解String,理解String很有必要。

1. 簡介

看看JDK中對String類的描述:

public final class String extends Object<br />implements Serializable, Comparable<String>, CharSequence 

該類是一個final類,子類無法繼承。實現了Serializable、Comparable<String>、CharSequence三個介面。很多公司的Java面試題,都會與String有關,畢竟處理字串是很頻繁的,再者很多演算法也和String有關。

2. intern方法

intern<br />public String intern()<br />返回字串對象的正常化表示形式。<br />一個初始為空白的字串池,它由類 String 私人地維護。<br />當調用 intern 方法時,如果池已經包含一個等於此 String 對象的字串(用 equals(Object) 方法確定),則返回池中的字串。否則,將此 String 對象添加到池中,並返回此 String 對象的引用。<br />它遵循以下規則:對於任意兩個字串 s 和 t,若且唯若 s.equals(t) 為 true 時,s.intern() == t.intern() 才為 true。<br />所有字面值字串和字串賦值常量運算式都使用 intern 方法進行操作。字串字面值在 Java Language Specification 的 §3.10.5 定義。<br />返回:<br />一個字串,內容與此字串相同,但一定取自具有唯一字串的池。 

在具體介紹intern方法之前,舉個例子,以便於更好地說明我的問題。

package mark.zhang;<br />public class Linux {</p><p>public static void main(String[] args) {<br />String s1 = "ubuntu";<br />String s2 = "ubuntu";<br />System.out.println(s1.equals(s2));//true<br />System.out.println(s1 == s2);//true</p><p>String s3 = new String("ubuntu");<br />String s4 = new String("ubuntu");<br />System.out.println(s3.equals(s4));//true<br />System.out.println(s3 == s4);//false<br />}<br />}<br /> 

我該保證,大多數人都是知道結果的。不過在這裡,我還是想用記憶體來分析一下結果。

 

字串常量會放在常量池中,(常量池主要存放字串常量和基本類型常量(public static final))。有些人的部落格中說常量放在data segement中,我想data segement主要用來存放靜態變數(這裡的變數是指成員變數,因為static不可以修飾局部臨時變數)和字串常量和基本類型常量等。所以,data segement可以分為靜態地區以及常量池等。

 

知道這些概念之後,分析上面代碼就會顯得很輕鬆啦,來吧,一起分析!!!

String s1 = "ubuntu"; 

這句代碼,執行時會在常量池中尋找是否有ubuntu,如果有的話,就指向它,沒有的話就自己建立。接著,建立s2,同理s2找到ubuntu,如是就不會自己再在常量池中建立ubuntu啦。這樣一來,s1和s2都指向了常量池中的ubuntu。

既然s1與s2都指向一個地方,所以 == 就是true。

String s3 = new String("ubuntu");<br />String s4 = new String("ubuntu"); 

那麼,我們看看,這兩句代碼的記憶體分析。首先需要明白,new出來的東西放在堆記憶體中。s3會先在常量池中看看有沒有ubuntu,沒有的話就先在常量池中建立一個,然後對中對象執行個體其實是常量池中的一份拷貝。s4發現常量池中已經存在ubuntu,直接在堆中拷貝一份。

從上面來看,s3、s4分別指向不同地址的ubuntu,所以二者就不會==。

好了,回到今天的主題intern方法。我想,如果你明白上面的內容,下面所講的東西對您來說就會很簡單,跟喝水差不多,呵呵!!

package mark.zhang;<br />public class Linux {</p><p>public static void main(String[] args) {<br />String s1 = "ubuntu";<br />String s2 = new String("ubuntu");<br />System.out.println("invoke intern before: ");<br />System.out.println(s1 == s2);//false<br />s2 = s2.intern();<br />System.out.println("invoke intern after: ");<br />System.out.println(s1 == s2);//true<br />}<br />} 

也許,你會問結果怎麼會與自己預想不一樣??從這個例子,可以明白intern返回的是常量池中的字串的值。只有這樣,兩個對象才會==,這也充分說明無論以哪種方式建立的字串對象,都會先在常量池中建立一個字串(內容即字面值)。再看下面一個例子,算是對intern及以上所說的一點補充吧?!

package mark.zhang;<br />public class Linux {</p><p>public static void main(String[] args) {</p><p>String s1 = new String("redhat");<br />String s2 = new String("redhat");<br />s2 = s2.intern(); // 返回常量池中的redhat<br />// 但是s1指向堆裡面的對象,而不是常量池中的redhat<br />System.out.println(s2 == s1);//false</p><p>String s3 = new String("redhat");<br />String s4 = new String("redhat");<br />s3 = s3.intern(); // 返回常量池中的redhat<br />s4 = s4.intern(); // 返回常量池中的redhat<br />System.out.println(s3 == s4);//true<br />}<br />}<br /> 

ok,收工!歡迎拍磚,共同進步! 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.