JAVA String對象的經典問題(new String())__JAVA

來源:互聯網
上載者:User

http://sarin.iteye.com/blog/603684/

 

 

  先來看一個例子,代碼如下:
Java代碼   public class Test {        public static void main(String[] args) {            String str = "abc";            String str1 = "abc";            String str2 = new String("abc");            System.out.println(str == str1);            System.out.println(str1 == "abc");            System.out.println(str2 == "abc");            System.out.println(str1 == str2);            System.out.println(str1.equals(str2));            System.out.println(str1 == str2.intern());            System.out.println(str2 == str2.intern());            System.out.println(str1.hashCode() == str2.hashCode());        }    }  

public class Test {public static void main(String[] args) {String str = "abc";String str1 = "abc";String str2 = new String("abc");System.out.println(str == str1);System.out.println(str1 == "abc");System.out.println(str2 == "abc");System.out.println(str1 == str2);System.out.println(str1.equals(str2));System.out.println(str1 == str2.intern());System.out.println(str2 == str2.intern());System.out.println(str1.hashCode() == str2.hashCode());}}


    如果您能對這8個輸出結果直接判斷出來,下面的分析就不用看了。但是我想還是有很多人對這個String對象這個問題只是表面的理解,下面就來分析一下Java語言String類和對象及其運行機制的問題。
    做個基礎的說明,堆(heap)記憶體和棧(Stack)記憶體的問題。堆和棧的資料結構這裡就不解釋了。Java語言使用記憶體的時候,棧記憶體主要儲存以下內容:基礎資料型別 (Elementary Data Type)和對象的引用,而堆記憶體儲存物件,棧記憶體的速度要快於堆記憶體。總結成一句話就是:引用在棧而對象在堆。
    Java中的比較有兩種,是==和equals()方法,equals()是Object類的方法,定義在Object類中的equals()方法是如下實現的:
Java代碼       public boolean equals(Object obj){            return (this==obj);    }  

public boolean equals(Object obj){return (this==obj);}


    String類重寫了equals()方法,改變了這些類型對象相等的原則,即判斷對象是否相等依據的原則為判斷二者的內容是否相等。
    瞭解以上內容後我們來說說String,String類的本質是字元數組char[],其次String類是final的,是不可被繼承的,這點可能被大多數人忽略,再次String是特殊的封裝類型,使用String時可以直接賦值,也可以用new來建立對象,但是這二者的實現機制是不同的。還有一個String池的概念,Java運行時維護一個String池,池中的String對象不可重複,沒有建立,有則作罷。String池不屬於堆和棧,而是屬於常量池。下面分析上方代碼的真正含義
Java代碼   String str = "abc";    String str1= "abc";  

String str = "abc";String str1= "abc";


    第一句的真正含義是在String池中建立一個對象”abc”,然後引用時str指向池中的對象”abc”。第二句執行時,因為”abc”已經存在於String池了,所以不再建立,則str==str1返回true就明白了。str1==”abc”肯定正確了,在String池中只有一個”abc”,而str和str1都指向池中的”abc”,就是這個道理。
Java代碼   String str2 = new String("abc");  

String str2 = new String("abc");


    這個是Java SE的熱點問題,眾所周知,單獨這句話建立了2個String對象,而基於上面兩句,只在棧記憶體建立str2引用,在堆記憶體上建立一個String對象,內容是”abc”,而str2指向堆記憶體對象的首地址。
    下面就是str2==”abc”的問題了,顯然不對,”abc”是位於String池中的對象,而str2指向的是堆記憶體的String對象,==判斷的是地址,肯定不等了。
    str1.equals(str2),這個是對的,前面說過,String類的equals重寫了Object類的equals()方法,實際就是判斷內容是否相同了。
    下面說下intern()方法,在JavaDoc文檔中,這樣描述了intern()方法:返回字串對象的正常化表示形式。怎麼理解這句話。實際上過程是這樣進行的:該方法現在String池中尋找是否存在一個對象,存在了就返回String池中對象的引用。
    那麼本例中String池存在”abc”,則調用intern()方法時返回的是池中”abc”對象引用,那麼和str/str1都是等同的,和str2就不同了,因為str2指向的是堆記憶體。
    hashCode()方法是返回字串內容的雜湊碼,既然內容相同,雜湊碼必然相同,那他們就相等了,這個容易理解。
再看下面的例子:
Java代碼   public class Test {        private static String str = "abc";        public static void main(String[] args) {            String str1 = "a";            String str2 = "bc";            String combo = str1 + str2;            System.out.println(str == combo);            System.out.println(str == combo.intern());        }    }  

public class Test {private static String str = "abc";public static void main(String[] args) {String str1 = "a";String str2 = "bc";String combo = str1 + str2;System.out.println(str == combo);System.out.println(str == combo.intern());}}


    這個例子用來說明用+連接字串時,實際上是在堆內容建立對象,那麼combo指向的是堆記憶體儲存”abc”字串的空間首地址,顯然str==combo是錯誤的,而str==combo.intern()是正確的,在String池中也存在”abc”,那就直接返回了,而str也是指向String池中的”abc”對象的。此例說明任何重新修改String都是重新分配記憶體空間,這就使得String對象之間互不干擾。也就是String中的內容一旦產生不可改變,直至產生新的對象。
    同時問題也來了,使用+連接字串每次都產生新的對象,而且是在堆記憶體上進行,而堆記憶體速度比較慢(相對而言),那麼再大量連接字串時直接+是不可取的,當然需要一種效率高的方法。Java提供的StringBuffer和StringBuilder就是解決這個問題的。區別是前者是安全執行緒的而後者是非安全執行緒的,StringBuilder在JDK1.5之後才有。不保證安全的StringBuilder有比StringBuffer更高的效率。
    自JDK1.5之後,Java虛擬機器執行字串的+操作時,內部實現也是StringBuilder,之前採用StringBuffer實現。
    歡迎交流,希望對使用者有用。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.