天天看點

java.lang.String--字元串字面量

String類的源碼介紹

All string literals in Java programs, such as "abc", are implemented as instances of this class. 

java中的所有字元串字面量都是String類的執行個體

For example: String str = "abc";

字元串字面量可以直接調用字元串類的方法,如下所示

System.out.println("rfdf".length());

字元串常量池

是一用來儲存字元串對象引用的容器。并且其中的内容不會重複。

即使字元串是不可變的,它仍然和Java中的其他對象一樣。對象都是建立在堆中,字元串也不例外。

是以字元串常量池仍然依靠堆,他們存儲的隻是堆中字元串的引用。

在JDK6.0及之前版本,字元串常量池存放在方法區中在JDK7.0版本以後,字元串常量池被移到了堆中了。在HotSpot VM裡實作string pool功能的是一個StringTable類,它是一個Hash表,預設值大小長度是1009;這個StringTable在每個HotSpot VM的執行個體隻有一份,被所有的類共享。

字元串字面量是怎麼加載到常量池中的

1、當一個.java檔案被編譯成.class檔案時,和所有其他常量一樣,每個字元串字面量都通過一種特殊的方式被記錄下來。

2、當一個.class檔案被加載時(注意加載發生在初始化之前),JVM在.class檔案中尋找字元串字面量。

3、當找到一個時,JVM會檢查是否有相等的字元串在常量池中存放了堆中引用。

如果找不到,就會在堆中建立一個對象,然後将它的引用存放在池中的一個常量表中。

4、一旦一個字元串對象的引用在常量池中被建立,這個字元串在程式中的所有字面量引用都會被常量池中已經存在的那個引用代替。

涉及字面量的一些問題

1、如果隻是字面量進行拼接如下所示

String c="3"+"45";

JVM會将它們優化成一個字面量即class檔案反編譯後的代碼如下所示

String c = "1223";

2、字元串建立的兩種方式以及差別

String a="345";

字面量"345"會首先去字元串常量池找是否有"345"這個字元串,如果有直接傳回引用,如果沒有則在堆中建立一個新對象并把該對象的引用存儲在常量池中并傳回該引用。

隻建立了一個對象

String b=new String("345");

在類加載時,首先判斷字元串常量池中是否存在"345"對象的引用,沒有則建立一個"345"對象,然後把這個對象的引用存放在字元串常量池中。

new關鍵字會在堆中建立一個新的對象。

b是在堆中的引用,而不是常量池中的。

故建立了一個(常量池中有)或者兩個對象(常量池中無)

3、如果拼接中存在字元串變量,JVM會将它們優化成StringBuilder進行拼接,然後通過StringBuilder.toString()擷取。

而StringBuilder.toString()是用new String的方式來擷取字元串,這種的會傳回堆中的字元串對象,而不是常量池中的對象。

public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }
           

String a="345";

String f="3";

String h=f+"45";

System.out.println(a==h);

結果為false

4、String的intern()方法

String的intern()方法是一個本地方法,定義為public native String intern(); intern()方法的價值在于讓開發者能将注意力集中到String池上。當調用 intern 方法時,如果池已經包含一個等于此 String 對象的字元串(該對象由 equals(Object) 方法确定),則傳回池中的字元串。否則,将此 String 對象添加到池中,并且傳回此 String 對象在常量池中的引用。例如:下面的代碼運作結果為true。

String str1 = new String("abc").intern();

String str2 = "abc";

System.out.println(str1 == str2);

5、為什麼不要在循環中去拼接字元串

因為字元串拼接在編譯時期JVM會将其優化成StringBuilder對象進行拼接,如果循環次數非常大的話,建立的StringBuilder對象非常的多,甚至可能會導緻記憶體溢出的情況。

垃圾回收

字元串字面量不會被垃圾回收。

原因

字面量存儲在堆中,但是在字元串常量池中一直會存在這個對象的引用。

字元串字面量總是有一個來自字元串常量池的引用。

Java面試題:java字元串字面量

Java中的字元串字面量

深入了解Java字元串常量池