Java String類實例化方式以及入池操作

 String類型是java中一種很重要的數據類型,但實際上,String是一個類,位於java.lang包下,定義如下:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence

 java.lang包存放着系統常用的基礎類,例如String,Object等,JDK1.1之後自動導入,所以我們在創建字符串的時候不需要import依賴包。

 String類實現了Serializable接口,可以進行序列化和反序列化。而且也實現了Comparable接口,並且覆寫了compareTo方法。CharSequence接口定義了字符序列相關的信息。

1. 實例化方式

 String有兩種實例化方式,一種是直接賦值,另一種是使用String類的構造方法進行實例化。

直接賦值

String str = "Hello World" ; 

 在任何的語言的底層,都不會提供有直接的字符串類型。字符串類型只是高級語言提供給用戶方便開發的支持而已。

 在java之中,本身也沒有直接提供字符串類型的概念,java本身提供的只有八大基本數據類型,而所有使用雙引號 ” “定義的字符串本質上來講都是String的匿名對象。

 所以,String通過直接賦值所創建的字符串就是在堆上的一個String匿名對象。

構造方法構造:

String str = new String("Hello World");

 雖然使用構造方法創建對象是最標準的創建方式,但是字符串創建一般推薦使用第一種方式。

2. 兩種實例化的區別

 String類的設計使用了共享設計模式。在JVM底層實際上會自動維護一個對象池(字符串對象池),如果現在採用了直接賦值的方式進行String類的對象實例化操作,那麼該實例化對象(字符串內容)將自動保存到這個對象池之中。如果下次繼續使用直接賦值的模式聲明String類對象,此時對象池之中如若有指定內容,將直接進行引用;如若沒有,則開闢新的字符串對象而後將其保存在對象池之中以供下次使用。所謂的對象池就是一個對象數組(目的就是減少開銷)。

 == 操作符兩端爲數字時,比較的是它們的值,如果是對象,比較的是它們的地址。那麼用其進行String直接賦值的驗證,如下:

String str1 = "hello" ;
String str2 = "hello" ;
String str3 = "hello" ;
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // true
System.out.println(str2 == str3); // true

 流程圖如下:

流程圖

 但是,如果使用構造方法進行String的創建,那麼每次new一次,就會直接在堆上創建新的字符串對象,而不會從池中獲取,看下面的語句:

String str = new String("hello") ;

 上面的過程實際上開闢了兩個字符串空間,首先是括號內的”hello”字符串,因爲所有雙引號引起的字符串都是String的匿名對象,然後是通過其new出來的新字符串,這兩者內容一樣,但是不是同一片空間,而且,str指向第二塊空間,第一塊字符串空間沒有指向,稱爲垃圾空間,如下圖所示:

流程

 另外,new出來的字符串是不會入池的,但是我們可以採用String提供的實例方法intern()將字符串進行入池操作。

 綜上,可以看出兩種方式的區別:

方式 特點
直接賦值 只會開闢一塊堆內存空間,並且該字符串對象可以自動保存在對象池中以供下次使用。
構造方法 會開闢兩塊堆內存空間,其中一塊成爲垃圾空間,不會自動保存在對象池中,可以使用intern()方法手工入池。

 推薦使用第一種,效率高而且語法簡單。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章