1. 程式人生 > 程式設計 >String intern淺析

String intern淺析

String存在的stringtable

  1. java中所有的類共享一個字串常量池。比如A類中需要一個“hello”的字串常量,B類也需要同樣的字串常量,他們都是從字串常量池中獲取的字串,並且獲得得到的字串常量的地址是一樣的。
  2. 實際上,為了提高匹配速度,即更快的查詢某個字串是否存在於常量池,Java在設計字串常量池的時候,使用了一張stringtable表,它裡面儲存了字串的引用,類似於HashMap,我們可以根據字串的hashcode找到對應entry,如果有衝突,它可能是一個entry連結串列,然後Java再遍歷entry連結串列,匹配引用對應的字串,如果找得到字串,返回引用,如果找不到字串,會把字串放到常量池中,並把引用儲存到stringtable裡。

怎麼樣才能進入字串常量池 -- 只有執行了ldc指令的字串才會進入字串常量池

凡是有雙引號括起字串的地方就會用到ldc指令,比如String a = "hello"。

intern的作用是把new出來的字串的引用新增到stringtable中,java會先計算string的hashcode,查詢stringtable中是否已經有string對應的引用了,如果有返回引用(地址),然後沒有把字串的地址放到stringtable中,並返回字串的引用(地址)。

  1. 因為有雙引號括起來的字串,所以會把ldc命令,即"test"會被我們新增到字串常量池,它的引用是string的char陣列的地址,會被我們新增到stringtable中。所以a.intern的時候,返回的其實是string中的char陣列的地址,和a的string例項化地址肯定是不一樣的。
    public static void main(String[] args) {
        String a = new String("test");
        System.out.println(a.intern() == a);//false
    }
複製程式碼
  1. new String("jo") + new String("hn")實際上會轉為stringbuffer的append 然後tosring()出來,實際上是new 一個新的string出來。在這個過程中,並沒有雙引號括起john,也就是說並不會執行ldc然後把john的引用新增到stringtable中,所以intern的時候實際就是把新的string地址(即e的地址)新增到stringtable中並且返回回來。
String e = new String("jo") + new String("hn");
        System.out.println(e.intern() == e);//true
複製程式碼