《Java 底層原理》String字符串詳解

前言

Java 字符串底層是如何存儲的,如何提高性能的,今天就來好好了解一下。

字符串的存儲結構

Jvm 有專門的字符串常量池用於存放字符串,存放字符串的數據結構是HashTable。

HashTable的數據結構如下:

看個案例:

public class StringDemo {
    public static void main(String[] args) {
        String a = "11";
        String b = new String("11");

        System.out.println("a的HashCode:"+a.hashCode());
        System.out.println("b的HashCode:"+b.hashCode());

        System.out.println("a==b :"+(a==b));   // 比較的指針地址
        System.out.println("a.equals(b) :"+ a.equals(b));   // 比較的是hashCode
    }
}

運行結果:

通過案例我們來詳細說明一下,Jvm如何創建一個String字符串的。

String 字符串會創建多少個Oop(Oop 是指Java 對象在Jvm中的存在形式)?

String a = "11";       

我們可以通過idea 來看創建了多少個Oop。

調式字符串賦值後。 char[] 和 String 都加一了。

說明創建了兩個Oop 

char[] 對應 TypeArrayKlass

String  對應  TypeArrayOopDesc

畫圖說明字符串在Jvm 中的存在形式:

String a = new String ("11");   -- 創建了3和Oop

再來看一下String 拼接的案例

public class StringDemo2 {
    public static void main(String[] args) {
        String s1 = "1";
        String s2 = "2";
        String s3 = s1+s2;
        String s4 = "12";
        System.out.println("s3 == s4: "+(s3 == s4));
    }
}

運行結果:

拼接字符串的實現原理用一句話完美解釋:

new StringBuilder(s1).append(s2).toString();    // toString 方法中有一個new String的邏輯。

並且拼接後的字符串是不放入常量池的。 看看toString 的源碼

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

new String(value, 0, count) ,這種方式創建的String 不放入常量池。

那有什麼方式可以將拼接的字符串放入常量池嗎?答案是肯定的。

public class StringDemo2 {
    public static void main(String[] args) {
        String s1 = "1";
        String s2 = "2";
        String s3 = s1+s2;
        s3.intern();       // 將拼接的字符串放入常量池
        String s4 = "12";
        System.out.println("s3 == s4: "+(s3 == s4));
    }
}

intern 方法就是將拼接的字符串放入常量池。

再來看一個案例:

public class StringDemo2 {
    public static void main(String[] args) {
        final String s1 = "1";
        final String s2 = "2";
        String s3 = s1+s2;
        String s4 = "12";
        System.out.println("s3 == s4: "+(s3 == s4));
    }
}

運行結果:

原因是s1,s2 都是final修飾,表示不會變,那麼String s3 = s1+s2; 其實也不會變,所以和 s3 = “12” 等價。   

總結

String 字符串對應數據存放在字符串常量池。

拼接字符串實際就是StringBuilder 拼接。

final 修飾的情況。

intern 方法的作用是 將字符串加入常量池。

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