Java String類詳解(一)

String類是一個字符串類型的類,使用“XXXX”定義的內容都是字符串,雖然這個類在使用上有一些特殊,但是String本身是一個類。

一、String的實例化兩種方式

1、直接賦值實例化:

String StringName= "xxx";

以上是String對象的直接賦值,以上的代碼並沒有使用關鍵字new進行。String類也是類,所以也有構造方法。

2、使用構造方法實例化:

public String(String str);

可以通過構造方法爲String類對象實例化,但在構造裏面依然要接收一個本類對象。

二、字符串的比較

如果要想知道兩個int型變量是否相等,使用“==”進行驗證,在String中也可以使用“==”來進行比較。我們來看一個例子:

public class StringDemo {
         public static void main(String args[]) {
                   String str1 = "Hello" ;
                   String str2 = new String("Hello") ;
                   String str3 = str2 ;        // 引用傳遞

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

運行結果:

false
false
true

發現使用“==”好象最終的判斷結果是不一樣的,爲什麼呢?下面通過內存關係圖來分析:

1

通過以上分析可以發現,“==”比較的不是字符串對象包含的內容,而是兩個對象所在的的內存對象的數值。所以“==”屬於數值比較,比較的是內存地址。

如果想比較字符串的內容,可以使用String類的equals()方法。

public class StringDemo {
         public static void main(String args[]) {
                   String str1 = "Hello" ;
                   String str2 = new String("Hello") ;
                   String str3 = str2 ;        // 引用傳遞
                   System.out.println(str1.equals(str2)) ;      
                   System.out.println(str1.equals(str3)) ;
                   System.out.println(str2.equals(str3)) ;      
         }
}

運行結果:

true
true
true

於是,現在比較的不是字符串的內存地址的數值,而是字符串的內容。

小結:
(1) ==:比較的是兩個字符串內存地址的數值是否相等,屬於數值比較;
(2)equals():比較的是兩個字符串的內容,屬於內容比較。

三、字符串常量是匿名對象

在各個語言中並沒有提供字符串的數據類型定義,很多語言都是使用字符數組來描述字符串的概念,在Java中也沒有字符串的概念,只是Java自己做了簡單處理。但是在Java中字符串依然不屬於基本數據類型,字符串是作爲String類的匿名對象的形式存在的。

字符串是匿名對象的驗證:

public class StringDemo {
         public static void main(String args[]) {
                   String str = "Hello" ;
                   // 通過字符串調用方法
                   System.out.println("Hello".equals(str)) ;
         }
}

運行結果:

true

匿名對象可以調用類中的方法與屬性,而以上的字符串調用了equals()方法,所以它一定是一個對象。

四、String類對象兩種實例化方式的區別

String類對象存在兩種實例化的操作形式,那麼這兩種有什麼區別,在開發之中應該使用那一種更好呢?

1、直接賦值的實例化方式:

  String str = "Hello" ;

此時,只分配了一塊堆內存空間和一塊棧內存空間:
11

再看一下代碼:

public class StringDemo {
         public static void main(String args[]) {
                   String str1 = "Hello" ;
                   String str2 = "Hello" ;
                   String str3 = "Hello" ;
                   System.out.println(str1 == str2) ;
                   System.out.println(str1 == str3) ;
                   System.out.println(str2 == str3) ;
         }
}

運行結果:

true
true
true

我們發現以上所有直接賦值的String類對象的內存地址完全相同,內存分配圖如下:

12

在設計String類的時候採用了一種稱爲共享設計模式的概念。在運行的JVM底層存在一個字符串的對象池(Object Pool),如果用戶採用了直接賦值的方式時,會將字符串的內容放入池保存,如果以後其他String對象繼續使用直接賦值方式實例化,並且設置了同樣的內容時,那麼將不會分配新的堆內存空間,而是使用已有對象的引用進行分配繼續使用。如果新聲明的字符串內容不在對象池中,則會分配一個新的,然後繼續放到池中以供下次使用。

2、採用構造方法實例化的方式:

使用構造方法實例化一定要用到new關鍵字,而一旦使用了new就表示要分配新的內存空間。

 String str = new String("Hello") ;

內存分配圖如下:

21

從上可以發現,分配了兩塊堆內存空間,其中一塊是垃圾。這樣處理內存的浪費外,使用構造方法定義的String類對象,其內容不會保存在對象中(因爲重新分配了新的一塊堆內存)。

現在希望使用構造方法定義的String類對象,其內容要保存在對象中,該怎麼辦麼?我們可以使用String類定義的一個手工入池的方法:

public String intern()

範例如下:

public class StringDemo {
         public static void main(String args[]) {
                   String str1 = new String("Hello").intern() ;
                   String str2 = "Hello" ;  // 入池
                   String str3 = "Hello" ;  // 使用池對象

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

運行結果:

true
true
true

小結:String類對象兩種實例化的區別?
(1)直接賦值實例化方式(String str = “xxx”):只會分配一塊堆內存空間,並且對象內容自動入池,以供重複使用;
(2)構造方法實例化方式(String str = new String(“xxx”)):會分配兩塊堆內存空間,其中有一塊是垃圾,並且不會自動入池,用戶可以使用intern()方法手動入池。

五、字符串的內容一旦定義則不可改變

先看一段代碼:

public class StringDemo {
         public static void main(String args[]) {
                   String str = "Hello " ;
                   str += "World " ;
                   str = str + "!!!" ;
                   System.out.println(str) ;
         }
}

運行結果:

Hello World !!!

我們通過內存分配圖分析一下:

31

通過以上的分析可以發現:字符串內容的更改,實際上改變的是字符串對象的引用過程,並且會伴隨有大量的垃圾出現,在實際開發中應該避免。

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