天天看點

深入探索 Java-String

1. 字元串常量池(Literal Pool)

   Java使用一個字元串常量池來統一儲存字元串的字面值,這樣可以複用,節省記憶體。

   字元串字字面值是一個由雙引号括起來的字元序列。它是指向一個String執行個體的引用。

   比如 String s = “abc”。對于“abc”,它首先是一個String literal,它在建立之後,立即利用String的intern方法,裝入到了字元串常量池并傳回這個String 執行個體的引用給s。當你再次寫abc”的時候,intern方法會先檢視是否已有這個literal了,就會直接傳回這個literal對應的String執行個體的引用。也就是說你循環1000變,記憶體裡面也隻有這麼一個String literal以及他對應的String的執行個體。

2. 編譯時計算和運作時計算的差別

   String s1 = "abc"; 

   String s2 = "abc"; 

   String s3 = s1 + s2;  // 運作時确定s3的值

   String s4 = "abc" + "abc";  // 編譯時在常量池會生成字元串字面值“abcabc”

   String s5 = "ab" + "cabc";  // 編譯時直接複用常量池中的字元串字面值“abcabc”

   System.out.println(s3 == s4);  // 傳回false

   System.out.println(s4 == s5);  // 傳回true

3. hashCode值

   Java對象統一存儲在哈希表中,使用對象時會根據hashCode值去擷取對象,如果兩個不同對象的hashcode相同,會在哈希表中發生沖突,

   哈希表中會通過連結清單來存儲這兩個不同對象。

   Java對象的hashCode值是根據Java對象的記憶體位址計算出相應的方法,函數hashCode是父類Object的方法,

   調用的是native方法。

   a、如果兩個對象相同(及a==b),那麼它們的hashCode值一定要相同;

   b、如果兩個對象的hashCode相同,它們并不一定相同;

4. String的equals()方法

   String類的equals()方法,覆寫了Object類的equals()方法,判斷目前字元串與傳進來的字元串的内容是否一緻。

   是以字元串相等的判斷是用equals()方法,而不是使用==。

   String中的equals()方法源代碼如下:

   public boolean equals(Object anObject) {

           if (this == anObject) {

               return true;

           }

           if (anObject instanceof String) {

               String anotherString = (String)anObject;

               int n = count;

               if (n == anotherString.count) {

                   char v1[] = value;

                   char v2[] = anotherString.value;

                   int i = offset;

                   int j = anotherString.offset;

                   while (n-- != 0) {

                       if (v1[i++] != v2[j++])

                           return false;

                   }

                   return true;

               }

           }

           return false;

       }

        Object對象quals()方法源代碼

        public boolean equals(Object o) {

                return this == o;//比較兩個對象是否相等

        }

5. String 類為什麼是final

       a. 字元串常量池(String pool, String intern pool, String保留池) 是Java堆記憶體中一個特殊的存儲區域, 當建立一個String對象時,假如此字元串值已經存在于常量池中,則不會建立一個新的對象,而是引用已經存在的對象。

   如下面的代碼所示,将會在堆記憶體中隻建立一個實際String對象.

   String s1 = "abcd"; 

   String s2 = "abcd”;

深入探索 Java-String

   假若字元串對象允許改變,那麼将會導緻各種邏輯錯誤,比如改變一個對象會影響到另一個獨立對象. 嚴格來說,這種常量池的思想,是一種優化手段.    

   b. 允許String對象緩存HashCode

   Java中String對象的哈希碼被頻繁地使用, 比如在hashMap 等容器中。

   字元串不變性保證了hash碼的唯一性,是以可以放心地進行緩存.這也是一種性能優化手段,意味着不必每次都去計算新的哈希碼.

   c. 安全性

   String被許多的Java類(庫)用來當做參數,例如 網絡連接配接位址URL,檔案路徑path,還有反射機制所需要的String參數等, 假若String不是固定不變的,将會引起各種安全隐患。

參考文檔

http://www.programcreek.com/2013/04/why-string-is-immutable-in-java/