• <track id="yjx63"><span id="yjx63"></span></track>
  • <track id="yjx63"></track>

  • 衡水天泰計算機培訓學校
    JAVA技術
    當前位置:首頁 > 學習專區 > JAVA技術 >

    Java中的字符串駐留

    來源:衡水北大青鳥 ????發布時間:2017-04-11 10:51 ????點擊:

    最近在工作的時候,一句再正常不過的代碼String a = “hello” + “world”;被改成了new StringBuilder().append(“hello”).append(“world”);當時就比較疑惑這樣做的好處,后來到網上查找了一番之后才清楚這與Java中的字符串駐留機制有關,那么什么是駐留呢?
    顧名思義,駐留就是在內存中保留(在Java中,我們通常稱駐留對象的地方為駐留池,不過它也是內存的一部分),它不僅存在于Java中,在C#中同樣存在。那么我就寫幾個例子來講解什么叫Java中字符串的駐留:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class test {
      public static void main(String[] args) {
          String a = "abc";
          String b = "abc";
          System.out.println(a == b);  // true
          String c = new String("abc");
          System.out.println(a == c);  // false
          System.out.println(a.equals()); // true  
      }
    }
    上面這段代碼在執行完String a = “abc”這一句的時候會在內存中創建一個值為abc的String類型對象。當執行下一句代碼,即String b = “abc”的時候,java會首先去駐留池里面查找是否有值為abc的字符串對象,如果有就讓b引用執行那個對象,如果沒有就新創建一個并且將其存放在駐留池中。所以,不難理解,當程序執行到第三句話的時候會返回true,我們知道==在java中比較的是對象的引用指向的對象的內存首地址是否一樣,而a和b指向的是同一個對象,所以會返回true。繼續往下走,當程序執行到String c = new String(“abc”)這句話的時候,java做的事包括: 檢查abc這個字符串對象是否在駐留池中,如果存在就把它當做值,然后再在堆上創建一個String類型的對象放到堆中(我們都知道在java中對象是放在堆中,對象的引用是存放在棧中)。所以這句話其實可能創建了2個對象(如果abc已經在駐留池中了,就只是在堆中創建了一個對象)。同時通過new String()創建出來的字符串對象是不會被放到駐留池中的。你也許會想,有沒有一種方法讓我把在堆中創建的對象放到駐留池中去呢?答案是有的!java提供了一個方法叫做intern(),如果執行c.intern(),會首先把c指向的對象放到駐留池中,然后返回指向這個對象的引用。那么,以下代碼會輸出什么呢!
    1
    2
    3
    4
    5
    6
    7
    8
    public class test {
      public static void main(String[] args) {
          String a = "abc";
          String b = new String("abc");
          System.out.println(a == b.intern());  // true
          System.out.println(a == b);  // false
      }
    }
    當然是true!不過它的執行過程還是值得說一下的,重點在b.intern();這句話上。經過上面的講解你也許會想過程應該是首先到堆中創建一個值為abc的String對象,然后將這個對象放到駐留池中。那么如果駐留池中已經存在值為abc的字符串對象了呢?那么b.intern會直接返回駐留池中的對象,所以這里會返回true。繼續向下執行,System.out.println(a == b);會返回false,因為在執行b.intern();這句話的時候,實際上是直接返回了駐留池中的對象,所以對原本b指向的堆中的對象沒有影響,所以a == b會返回false。
    我通過上面這個例子簡單講解了java中的字符串駐留,那么現在回到文章開始部分的疑惑去,為什么使用StringBuilder而不是簡單地使用”+”來連接字符串呢?經過上面的講解,你可能會猜測StringBuilder用了字符串駐留,而”+”不是。恭喜你,你答對了,加10分。但是你也許并不知道使用”+”的時候tricky的地方在哪里。繼續往下看。
    原因在于使用+連接字符串每次都生成新的對象,而且是在堆內存上進行,而堆內存速度比較慢(相對而言),那么再大量連接字符串時直接+是不可取的,當然需要一種效率高的方法。Java提供的StringBuffer和StringBuilder就是解決這個問題的。區別是前者是線程安全的而后者是非線程安全的。所以促使我寫這篇博客的問題的原因就找到了。此外,值得注意的一點是,駐留池是不會被GC回收的,它會在程序運行期間一直保留。
    最后我還想再說點題外話,請看下面這段程序:
     
    public class test {
      public static void main(String[] args) {
          String a = "a";
          String b = "b";
          String c = "ab";
          String d = "a" + "b";
          String e = a + "b";
          String f = a + b;
          System.out.println(c == d);  // true
          System.out.println(c == e);  // false
          System.out.println(c == f);  // false
          System.out.println(d == e);  // false
          System.out.println(d == f);  // false
          System.out.println(e == f);  // false
      }
    }
    c == d輸出true,因為c和d都是字符串常量,他們的值在編譯時就確定了。而所有涉及到引用的地方都是在運行時才確定值的,所有下面會全部輸出為false。
    掃一掃 加關注 精彩資訊在這里!

    技能認證

    OSTA技能證書,全國可查,真實可信

    多項熱門專業自由選擇

    豐富的專業課程設置,完全自由選擇

    畢業推薦就業

    5重就業保障體系,4項就業指導服務

    學校地址

    最方便的乘車路線

    在線咨詢

    來校講解答疑

    在線咨詢

    399入學禮包

    報名熱線

    0318-2888080

    • 版權所有2015~2021 衡水天泰計算機培訓學校
      北大青鳥課程咨詢電話:0318-2888080 官方網址:www.lv2012gf.com
      地址:河北省衡水市育才街與勝利交叉口南行200米路東 郵編:053000
      (網站客服咨詢QQ:3142643279)
    • 網站備案/許可證號:冀ICP備19035316號-1
    日韩无码国产精品97精品|国产人妻无码一区二区三区动态|欧美97欧美色伦综合视频在线看|人妻少妇中文字幕乱码高清|

  • <track id="yjx63"><span id="yjx63"></span></track>
  • <track id="yjx63"></track>