智漁課堂官方免費教程十九:Java常用類之String類

String類

首先,String是引用類型,也是唯一一個可以不使用關鍵字new創建對象的引用類型,因爲有字符串常量值,使用英文格式的雙引號""括起來就是字符串常量值。
創建對象的兩種方式
      方式一、String  s1 = “abc”;
      方式二、String  s2 = new  String(“abc”);
      這兩種方式都是創建了一個字符串對象,值都是字符串abc;
不同的是
      方式一是直接使用字符串常量abc賦值給變量s1,此時系統先到常量池中查找有沒有字符串常量abc,如果有將字符串常量abc在常量池中的地址賦值給變量s1,如果沒有會將字符串常量abc加入到常量池中,並把地址賦值給變量s1。
      而方式二是在堆內存中創建一個String類型的對象,在這個對象中存儲着字符串abc
其次,String類型被設計成不可變的,即對象不可變;一旦對象被創建,這個對象將無法被修改,引用(變量)是可以修改;如上例中s1是引用(變量),它可以存儲其他字符串的地址,但是字符串abc本身被創建後無法再改變了。

實例:
      //創建一個String類型的對象
      String  s = "abc";
      //如果要將變量s的修改爲"abcxyz",代碼如下
      s = s+"xyz";
      //輸出結果爲:abcxyz
      System.out.println(s);
      //由於這裏使用兩個字符串常量相連接,系統會默認當成一個字符串,即"abcxyz" 
      String  s1 = "abc" + "xyz"; 
      String  s2 = "abcxyz";
      其中第二行代碼會先到常量池中查找有沒有字符串xyz,如果沒有將字符串xyz加入到常量池中,此時常量池中有abc和xyz兩個字符串常量;
      然後系統底層會默認在堆中創建一個StringBuilder類型的對象;然後用StringBuilder對象的append方法,將兩個字符串連接到一起,最後再調用toString方法返回連接後的字符串abcxyz,並將返回的字符串abcxyz的地址賦值給變量s。

接下來驗證實例中變量s、s1和s2三個變量,引用的是不是一個對象。可以使用雙等號來進行判斷。
      //輸出結果爲:false
      System.out.println(s == s1); 
      //輸出結果爲:true
      System.out.println(s1 == s2); 
      由以上結果可以看出,變量s1和s2中存儲的是同一字符串對象的地址,而變量s中存儲的是另一字符串對象的地址,但這兩個字符串對象的內容是相同的(都是abcxyz);那麼如何判斷兩個字符串的內容是否相同呢?

在String類中已經重寫了父類Object中的equals方法,通過equals方法可以判斷兩個字符串內容是否相同
      //輸出結果爲:true
      System.out.println(s.equals(s1)); 


總結:
當使用字符串常量時,系統會先到常量池中尋找,如果沒找到,將字符串常量加入到常量池中。
使用關鍵字new創建的字符串對象保存在堆內存中。
使用字符串連接符+連接兩個字符串常量時,系統會自動將它們當成一個字符串常量,並將其存儲在常量池中
使用字符串連接符+字符串變量時,連接後的字符串存儲在堆內存中
比較兩個字符串的內容是否相同使用equals方法 

所有引用類型使用雙等號==比較時,比較的是對象地址是否相同,即是否是同一對象


以下內容初學者選讀
//類A的源碼
public class A{
	String s = "abc" + "d";
}
//打開字節碼文件的命令:javap -verbose A
//以下是類A編譯後class文件的內容
//關鍵行#2和5: ldc,可以看到Java編譯器是將"abc" + "d"當做"abcd"來處理的
Classfile /H:/A.class
  Last modified 2015-5-29; size 239 bytes
  MD5 checksum 271095a9d37f742c9bdefa883c6b9a00
  Compiled from "A.java"
public class A
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #5.#14         // java/lang/Object."<init>":()V
   #2 = String             #15            // abcd
   #3 = Fieldref           #4.#16         // A.s:Ljava/lang/String;
   #4 = Class              #17            // A
   #5 = Class              #18            // java/lang/Object
   #6 = Utf8               s
   #7 = Utf8               Ljava/lang/String;
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               SourceFile
  #13 = Utf8               A.java
  #14 = NameAndType        #8:#9          // "<init>":()V
  #15 = Utf8               abcd
  #16 = NameAndType        #6:#7          // s:Ljava/lang/String;
  #17 = Utf8               A
  #18 = Utf8               java/lang/Object
{
  java.lang.String s;
    descriptor: Ljava/lang/String;
    flags:

  public A();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String abcd
         7: putfield      #3                  // Field s:Ljava/lang/String;
        10: return
      LineNumberTable:
        line 1: 0
        line 2: 4
}
SourceFile: "A.java"

//類B源碼
public class B{
	String s = "abc";
	String s1 = s+"d";
}
//類B的class文件
//首先看#2和#7,這裏不在是當做一個字符串來處理的了
//然後看5: ldc和25: ldc,這兩行是將兩個字符串常量壓棧
//11: new,這裏創建了一個StringBuilder類的對象
//22: invokevirtual和27: invokevirtual調用了StringBuilder對象的append方法,將兩個字符串追加到一起
//最後30: invokevirtual,調用了StringBuilder對象的toString方法,獲得連接後的字符串"abcd"
Classfile /H:/B.class
  Last modified 2015-5-29; size 443 bytes
  MD5 checksum 3eaa63a1c104ccfe26e2a6f9df85d93c
  Compiled from "B.java"
public class B
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #11.#21        // java/lang/Object."<init>":()V
   #2 = String             #22            // abc
   #3 = Fieldref           #10.#23        // B.s:Ljava/lang/String;
   #4 = Class              #24            // java/lang/StringBuilder
   #5 = Methodref          #4.#21         // java/lang/StringBuilder."<init>":()V
   #6 = Methodref          #4.#25         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #7 = String             #26            // d
   #8 = Methodref          #4.#27         // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #9 = Fieldref           #10.#28        // B.s1:Ljava/lang/String;
  #10 = Class              #29            // B
  #11 = Class              #30            // java/lang/Object
  #12 = Utf8               s
  #13 = Utf8               Ljava/lang/String;
  #14 = Utf8               s1
  #15 = Utf8               <init>
  #16 = Utf8               ()V
  #17 = Utf8               Code
  #18 = Utf8               LineNumberTable
  #19 = Utf8               SourceFile
  #20 = Utf8               B.java
  #21 = NameAndType        #15:#16        // "<init>":()V
  #22 = Utf8               abc
  #23 = NameAndType        #12:#13        // s:Ljava/lang/String;
  #24 = Utf8               java/lang/StringBuilder
  #25 = NameAndType        #31:#32        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #26 = Utf8               d
  #27 = NameAndType        #33:#34        // toString:()Ljava/lang/String;
  #28 = NameAndType        #14:#13        // s1:Ljava/lang/String;
  #29 = Utf8               B
  #30 = Utf8               java/lang/Object
  #31 = Utf8               append
  #32 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #33 = Utf8               toString
  #34 = Utf8               ()Ljava/lang/String;
{
  java.lang.String s;
    descriptor: Ljava/lang/String;
    flags:

  java.lang.String s1;
    descriptor: Ljava/lang/String;
    flags:

  public B();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String abc
         7: putfield      #3                  // Field s:Ljava/lang/String;
        10: aload_0
        11: new           #4                  // class java/lang/StringBuilder
        14: dup
        15: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
        18: aload_0
        19: getfield      #3                  // Field s:Ljava/lang/String;
        22: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        25: ldc           #7                  // String d
        27: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        30: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        33: putfield      #9                  // Field s1:Ljava/lang/String;
        36: return
      LineNumberTable:
        line 1: 0
        line 2: 4
        line 3: 10
}
SourceFile: "B.java"

//類C源碼
public class C{
	String s = new String("abc");
	String s1 = s+"d";
}
//C.class文件內容
//這裏主要演示類B中String s = "abc";和類C中String s = new String("abc");的區別
//首先5: new 這裏創建了一個String對象
//然後9: ldc 字符串常量"abc"被壓棧
//最後11: invokespecial 初始化String對象
//而類B只有ldc將常量壓棧這一步
Classfile /H:/C.class
  Last modified 2015-5-29; size 506 bytes
  MD5 checksum 97026d45729fe35e1f470e17e1b5f0e0
  Compiled from "C.java"
public class C
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #13.#23        // java/lang/Object."<init>":()V
   #2 = Class              #24            // java/lang/String
   #3 = String             #25            // abc
   #4 = Methodref          #2.#26         // java/lang/String."<init>":(Ljava/lang/String;)V
   #5 = Fieldref           #12.#27        // C.s:Ljava/lang/String;
   #6 = Class              #28            // java/lang/StringBuilder
   #7 = Methodref          #6.#23         // java/lang/StringBuilder."<init>":()V
   #8 = Methodref          #6.#29         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #9 = String             #30            // d
  #10 = Methodref          #6.#31         // java/lang/StringBuilder.toString:()Ljava/lang/String;
  #11 = Fieldref           #12.#32        // C.s1:Ljava/lang/String;
  #12 = Class              #33            // C
  #13 = Class              #34            // java/lang/Object
  #14 = Utf8               s
  #15 = Utf8               Ljava/lang/String;
  #16 = Utf8               s1
  #17 = Utf8               <init>
  #18 = Utf8               ()V
  #19 = Utf8               Code
  #20 = Utf8               LineNumberTable
  #21 = Utf8               SourceFile
  #22 = Utf8               C.java
  #23 = NameAndType        #17:#18        // "<init>":()V
  #24 = Utf8               java/lang/String
  #25 = Utf8               abc
  #26 = NameAndType        #17:#35        // "<init>":(Ljava/lang/String;)V
  #27 = NameAndType        #14:#15        // s:Ljava/lang/String;
  #28 = Utf8               java/lang/StringBuilder
  #29 = NameAndType        #36:#37        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #30 = Utf8               d
  #31 = NameAndType        #38:#39        // toString:()Ljava/lang/String;
  #32 = NameAndType        #16:#15        // s1:Ljava/lang/String;
  #33 = Utf8               C
  #34 = Utf8               java/lang/Object
  #35 = Utf8               (Ljava/lang/String;)V
  #36 = Utf8               append
  #37 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #38 = Utf8               toString
  #39 = Utf8               ()Ljava/lang/String;
{
  java.lang.String s;
    descriptor: Ljava/lang/String;
    flags:

  java.lang.String s1;
    descriptor: Ljava/lang/String;
    flags:

  public C();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: new           #2                  // class java/lang/String
         8: dup
         9: ldc           #3                  // String abc
        11: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
        14: putfield      #5                  // Field s:Ljava/lang/String;
        17: aload_0
        18: new           #6                  // class java/lang/StringBuilder
        21: dup
        22: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V
        25: aload_0
        26: getfield      #5                  // Field s:Ljava/lang/String;
        29: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        32: ldc           #9                  // String d
        34: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        37: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        40: putfield      #11                 // Field s1:Ljava/lang/String;
        43: return
      LineNumberTable:
        line 1: 0
        line 2: 4
        line 3: 17
}
SourceFile: "C.java"


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