JAVA 基礎知識點複習(三)引用數據類型 String


這系列博文主要是將自己之前學習的一些java基礎內容進行歸納與總結。

常用方法

int length() // 獲取長度
char charAt(int index) // 獲取對應角標的字符
int indexOf(String str) // 獲取對應角標
String substring(int beginIndex, int endIndex) // 截取區間返回 包含開頭不包含結尾
String[] split(String regex, int limit) // 根據正則表達式分隔字符,limit應用次數
String trim() // 忽略前後空白
String replace(char oldChar, char newChar) // 替換
char[] toCharArray() // 分解成字符數組
String intern()  // 判斷常量池是否存在該字符串,如果存在則返回,否則在常量池記錄首次出現的引用(jdk1.7後)

Sting對equals方法的重寫

// Object的equals方法 直接通過==比較內存地址
    public boolean equals(Object obj) {
        return (this == obj);
    }

// String對equals方法進行了重寫 先比較內存地址如果不相等再比較字符串值是否相同
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            .... // 逐個char進行比較
        }
}

String的比較

String s1 = new String("aaa");
String s2 = "aaa";
System.out.println(s1 == s2); // false

s1 = new String("bbb").intern();
s2 = "bbb";
System.out.println(s1 == s2); // true

s1 = "ccc";
s2 = "ccc";
System.out.println(s1 == s2); // true

s1 = new String("ddd").intern();
s2 = new String("ddd").intern();
System.out.println(s1 == s2); // true

s1 = "ab" + "cd";
s2 = "abcd";    
System.out.println(s1 == s2); // true

String temp = "hh";
s1 = "a" + temp;
// 如果調用s1.intern 則最終返回true
s2 = "ahh";
System.out.println(s1 == s2); // false

temp = "hh".intern();
s1 = "a" + temp;
s2 = "ahh";
System.out.println(s1 == s2); // false

temp = "hh".intern();
s1 = ("a" + temp).intern();
s2 = "ahh";
System.out.println(s1 == s2); // true

s1 = new String("1"); // 同時會生成堆中的String對象 以及常量池中的"1",但是此時s1是指向堆內存的String對象
s1.intern(); // 返回的是常量池中的已經存在"1"的引用
s2 = "1"; // 還是指向常量池中已存在的"1"
System.out.println(s1 == s2);    // false

// 先調用intern
String s3 = new String("1") + new String("1"); // 此時生成了四個對象 常量池中的"1" + 2個堆中的"1" + s3指向的堆中的對象(注此時常量池不會生成"11")
s3.intern();    // jdk1.7之後,常量池不僅僅可以存儲對象,還可以存儲對象的引用,會直接將s3的地址存儲在常量池
String s4 = "11";    // jdk1.7之後,常量池中的地址其實就是s3的地址
System.out.println(s3 == s4); // jdk1.7之前false, jdk1.7之後true

// 後調用intern
s3 = new String("2") + new String("2");
s4 = "22";        // 常量池中不存在22,所以會新開闢一個存儲22對象的常量池地址
s3.intern();    // 常量池22的地址和s3的地址不同,若 s3 = s3.intern() 則爲true
System.out.println(s3 == s4); // false

String在內存中的對象創建

  • 字符串相加如果沒有任何變量參與,則編譯器對String做了優化,會直接拼接轉化爲一個字符串
  • 若有變量參與則是通過new StringBuild().append()相加
  • new String(“E”) + new String(“F”) 一共創建了五個變量
String s1 = "A" + "B" + "C"; // 直接在常量池中創建 "ABC"
// 字節碼:
    Code:
       0: ldc           #2                  // String ABC
       2: astore_1
       3: return
           
String s2 = s1 + "D"; // 在堆中new StringBuilder,通過append相加
// 字節碼:
    Code:
       0: ldc           #2                  // String ABC
       2: astore_1
       3: new           #3                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      10: aload_1
      11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      14: ldc           #6                  // String D
      16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: astore_2
      23: return
    
String s3 = new String("E") + new String("F"); // 創建了五個對象, 常量池中的"E"、"F",堆中的"E"、"F",s3指向堆中的對象
// 字節碼:
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
       7: new           #4                  // class java/lang/String
      10: dup
      11: ldc           #5                  // String E
      13: invokespecial #6                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      16: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: new           #4                  // class java/lang/String
      22: dup
      23: ldc           #8                  // String F
      25: invokespecial #6                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      28: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      31: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      34: astore_1
      35: return

IDEA中在控制檯打印執行的字節碼

在Setting中配置External Tools

在這裏插入圖片描述參數說明

Name: Show Byte Code (隨意)
Program: C:\Program Files\Java\jdk1.8.0_144\bin\javap.exe (jdk bin目錄下的javap.exe)
Arguments: -c $FileClass$ (照填)
Working directory: $OutputPath$ (照填)

然後右鍵執行即可

在這裏插入圖片描述

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