分析String在記憶體中的表現

奮鬥的小青年_發表於2017-08-27

建立字串的方法有兩種:

         Stringstr1=”直接賦值法”

         Stringstr2=new String(“通過new關鍵字的方法來建立”);

那麼這兩種建立方式有什麼區別呢?下面通過一個Demo來測試一下

[java] view plain copy
 print?
  1. package test;  
  2.   
  3. public class Demo {  
  4.     public static void main(String[] args) {  
  5.         String str1="java";  
  6.         String str2="java";  
  7.         String str3=new String("java");  
  8.         String str4=new String("java");  
  9.           
  10.         System.out.println(str1==str2);     //true  
  11.         System.out.println(str1==str3);     //false  
  12.         System.out.println(str3==str4);     //false  
  13.         System.out.println(str3.equals(str4));  //true  
  14.     }  
  15. }  

知道了它們執行後的區別了,那麼他的原理是什麼呢?

在執行String str1=”Java”建字串的時候,jvm會首先檢查字串常量池中是否存在該字串物件,如果已經存在,那麼就不會在建立字串常量池中再建立了,直接返回該字串在字串常量池中記憶體地址,如果該字串還不存在字串常量池中,那麼就會在字串常量。池中先建立該字串的物件,然後再返回。所以在執行String str2=”java”的時候,因為字串常量池中已經存在”java”字串物件了,就不會在字串常量池中再建立了,所以在棧記憶體中str1和str2的記憶體地址都是指向”java”在字串常量池的位置。

在執行String str3=new String(“java”)建立字串的時候,jvm首先會檢查字串常量池中是否存在”java”的字串,如果已經存在,則不會在字串常量池中建立了,如果沒有存在,那麼就會在字串常量池中建立”java”字串物件,然後還會到堆記憶體中再建立一份字串物件,把字串常量池中的”java”字串內容拷貝到記憶體中的字串物件,然後返回堆記憶體中字串物件的記憶體地址。即棧記憶體儲存的地址是堆記憶體的記憶體地址。String str4=new String(“java”)是在堆記憶體中又建立了一個物件,所以str3==str4返回的是false。用一張圖來表示一下。

知道這些以後就知道前三個的輸出結果的原因了。那麼為什麼

System.out.println(str3.equals(str4));這個執行結果會返回true呢?通過看原始碼可以知道,在Object類中equals的方法是比較兩個物件的記憶體地址

[java] view plain copy
 print?
  1. public boolean equals(Object obj) {  
  2.     return (this == obj);  
  3.     }  

在String類中對equals方法進行了重寫,原始碼是這樣的。

[java] view plain copy
 print?
  1.    public boolean equals(Object anObject) {  
  2. if (this == anObject) {  
  3.     return true;  
  4. }  
  5. if (anObject instanceof String) {  
  6.     String anotherString = (String)anObject;  
  7.     int n = count;  
  8.     if (n == anotherString.count) {  
  9.     char v1[] = value;  
  10.     char v2[] = anotherString.value;  
  11.     int i = offset;  
  12.     int j = anotherString.offset;  
  13.     while (n-- != 0) {  
  14.         if (v1[i++] != v2[j++])  
  15.         return false;  
  16.     }  
  17.     return true;  
  18.     }  
  19. }  
  20. return false;  
  21.    }  

在String中的equals方法中會先判斷兩個物件的記憶體地址是否相等,如果相等,那麼equals就return true,如果不相等,則會進一步判斷傳過來的物件是不是字串型別的,如果是則將兩個字串物件char陣列,然後一個一個字元的比較,如果都相等,則返回true。

相關文章