1.1 簡介:java
String是一個複製類型,在java項目中使用最多。在java中String變量值都是存放的String在堆空間中的地址。本文講解下String的地址相關常量池和intern。express
2.2 String的組成:數組
a.數組被放在堆空間。this
b.數組不能改變大小,每一次改變大小都會從新分配空間(地址改變)。spa
2.4 經常使用的方法code
能夠去下載幫助文檔(chm文件)查看。對象
2.1 初始化
ci
a. ==要相等,必須在class文件在加載時,能讓JVM解析並生成的char[]在常量池中。
文檔
b. =初始化,JVM直接解析,而後從常量池中尋找相同的值地址空間,並返回;若是沒有值,則建立並返回。
字符串
c. new初始化時,將變量值存放爲new String()開闢的堆空間地址,而後在堆空間地址中存放常量池中一樣值的char[]地址,若是沒有則建立並返回
d. 只有JVM在解析的時候,可以準確的知道=右值的準確地址(包括能夠經過final引用查找到其值,不包括引用地址),則其地址空間都相等。
public static void main(String[] args) { final String o1="a"; String o = "a"; String a = "a1"; String b = "a" + 1; String c = o + 1; String c1 = o1 + 1; String d = new String("a1"); /** * String a: 右值是肯定的基礎變量,沒有引用、new等初始化方式,在加載的時候、JVM解析class文件,a直接存放char[]的地址 * String b: 雖然右值使用了+,可是JVM直接將其整合爲char[],放在堆空間 * String c: 引用,JVM只有在加載後,運行時才能去人地址 * String c1:雖然使用的是引用,可是有final,JVM能夠直接解析 * String d: d指向的是,new 在運行時分配堆空間。 */ System.out.println(a == b); // true System.out.println(a == c); // false System.out.println(a == c1); // true System.out.println(a == d); // false System.out.println(a.intern()); System.out.println(a.hashCode()); // 3056 System.out.println(b.hashCode()); // 3056 }
2.2 intern
源碼解釋:
Returns a canonical representation for the string object. A pool of strings, initially empty, is maintained privately by the class String. When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true. All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of theThe Java™ Language Specification. 返回一個標準的String對象。 String池,開始是空的,用來保存私有的String類。 1.用intern()時:若是這String池裏面有一個可以equals(objects)《即,有一個相同值的char[]》,則返回這個char[];若是沒有,則添加建立一個,並返回。 2.兩個String字符串 s和t,只有在s.equals(t)<值相同>的狀況下,t.intern()==s.intern()爲true。
案例:
public static void main(String[] args) { String a = "a1"; /* * intern 返回String常量池中地址;相同Unicode的地址引用 將一個 String 類的保存到一個全局 String 表中 , * 若是具備相同值的 Unicode 字符串已經在這個表中,那麼該方法返回表中已有字符串的地址, * 若是在表中沒有相同值的字符串,則將本身的地址註冊到表中 */ System.out.println("============== 基礎變量 ==============="); String c00 = "a".intern() + 1; // 方法在,runtime確認 String c01 = "a" + 1; //加載時,確認地址 System.out.println(a == c00); // false System.out.println(a == c01);// true System.out.println(a == c00.intern()); //(true) runtime方法運行、返回指向的常量池地址 System.out.println("============== final 引用 ==============="); final String b1 = "a"; // 運行時確認值 String c10 = b1.intern() + 1; String c11 = b1 + 1; System.out.println(a == c10); // false System.out.println(a == c11); // true System.out.println(a == c01.intern()); //true runtime方法運行、返回指向的常量池地址 System.out.println("============== 引用 ==============="); String b2 = a; // 運行時確認值 String c20 = b2.intern() + 1; String c21 = b2 + 1; System.out.println(a == c20); // false System.out.println(a == c21); // System.out.println("==============final new 初始化==============="); final String b3 = new String("a"); // NEW 運行時確認值 String c30 = b3.intern() + 1; String c31 = b3 + 1; System.out.println(a == c30); // false System.out.println(a == c31); // false System.out.println("============== new ==============="); String b4 = new String("a"); // final new 運行時確認值 String c40 = b4.intern() + 1; String c41 = b4 + 1; System.out.println(a == c40); // false System.out.println(a == c41); // true System.out.println("============== method ==============="); final String b5 = getB3(); // 方法運行時確認值 String c50 = b5.intern() + 1; // 對於引用,可是運行時JVM才知道其值 String c51 = b5 + 1; // 對於引用,可是運行時JVM才知道其值 System.out.println(a == c50); // false System.out.println(a == c51); // true (說明在同一個常量池) System.out.println("============== final method ==============="); final String b6 = getB4(); // final方法,運行時確認 String c60 = b6.intern() + 1; // 對於引用,可是運行時JVM才知道其值 String c61 = b6 + 1; // 對於引用,可是運行時JVM才知道其值 System.out.println(a == c60); // false System.out.println(a == c60); // true (說明在同一個常量池) } public static String getB3() { return "a"; } public final static String getB4() { return "a"; }