国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

關于String.intern()和new StringBuilder("").

derek_334892 / 3742人閱讀

摘要:對比較返回是因為這個字符串在執之前已經出現過,字符串常量池中已經有它的引用了,不符合首次出現的原則,而計算機軟件這個字符串則是首次出現的,因此返回。

在《深入理解Java虛擬機》書中,提到在jdk1.7的版本中用String.intern()返回引用。

public class RuntimeConstantPoolOOM {
    public static void main(String[]args) {
        String str1=new StringBuilder("計算機").append("軟件").toString();
        System.out.println(str1.intern()==str1);
        String str2=new StringBuilder("ja").append("va").toString();
        System.out.println(str2.intern()==str2);
    }

}

運行結果:true false
書中給的解釋是:

JDK 1.7(以及部分其他虛擬機,例如JRockit)的intern()實現不會再復制實例,只是在常量池中記錄首次出現的實例引用,因此intern()返回的引用和由StringBuilder創建的那個字符串實例是同一個。對str2比較返回false是因為“java”這個字符串在執StringBuilder.toString()之前已經出現過,字符串常量池中已經有它的引用了,不符合“首次出現”的原則,而“計算機軟件”這個字符串則是首次出現的,因此返回true。

現在的疑問是“java”這個字符串在常量池中什么時候存在了?
我最開始的猜想是“java”這個字符串是不是常駐在常量池中的?那為什么常駐在常量池中呢?Java虛擬機什么時候加載了“java”這個字符串?

最開始以為是StringBuilder的原因,查看了一下StringBuilder的源碼,發現里面沒有加載字符串常量,網上也找了關于intern()的,發現都只是對比JDK 1.6和JDK 1.7之間上面代碼的運行結果比較,后來找了許久,終于找到一篇關于[String.intern()探究]: 的文章,發現要去查看System的源碼.

java虛擬機會自動調用System類

/* register the natives via the static initializer.
 *
 * VM will invoke the initializeSystemClass method to complete
 * the initialization for this class separated from clinit.
 * Note that to use properties set by the VM, see the constraints
 * described in the initializeSystemClass method.
 */
在System類中的注釋可以知道,調用了initializeSystemClass方法,在此方法中調用了Version對象的init靜態方法
sun.misc.Version.init();
因此sun.misc.Version類會在JDK類庫的初始化過程中被加載并初始化。
查看Version類定義的私有靜態字符串常量如下:
private static final String launcher_name = "java";
private static final String java_version = "1.7.0_51";
private static final String java_runtime_name = "Java(TM) SE Runtime Environment";
private static final String java_runtime_version = "1.7.0_51-b13";
在初始化Version類時,對其靜態常量字段根據指定的常量值做默認初始化,所以"java"被加載到了字符串常量池中,修改上面代碼使字符串值為上面常量中的任意一個都會返回false。
String str2=new StringBuilder("1.7.0").append("_51").toString();
System.out.println(str2.intern()==str2);

這個問題解決了,然后我又發現了另外一個問題。除了這些在虛擬機加載時就初始化的常量,定義其他的字符串常量,比如“nihao”.

先運行這個代碼
String str3 = new StringBuilder("ni").append("hao").toString();
System.out.println(str3==str3.intern());
通過上面的解釋,運行結果為true.
在運行這個代碼
String str3 = new StringBuilder("nihao").toString();
System.out.println(str3==str3.intern());
其結果是什么?應該還是true吧,畢竟通過上一個運行結果可以知道"nihao"這個字符串常量沒有被預先加載到常量池中。
但是運行結果卻是false.

我現在還沒想通這個問題,StringBuilder的append方法沒有改變字符串的引用地址,只是把其值改變了,為什么加了append返回的是true,沒有加append卻是false呢?如果在后面多加幾個append返回的也是true。
也希望有人可以解答一下這個問題

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67760.html

相關文章

  • String的內存模型,為什么String被設計成不可變的

    摘要:證明返回常量池中已存在的對象,不等于新建的對象。為什么要設計成一下內容來自發現百度的中文版本基本也是此文的翻譯版。總之,安全性和字符串常量池緩存是被設計成不可變的主要原因。 String是Java中最常用的類,是不可變的(Immutable), 那么String是如何實現Immutable呢,String為什么要設計成不可變呢? 前言 關于String,收集一波基礎,來源標明最后,不確...

    vspiders 評論0 收藏0
  • 關于 String.intern() 的思考

    摘要:我看到一個上的問題是關于的感覺比較有意思于是自己也去探索了一下有了一些自己的見解于是在此記錄下來我們首先來看一個例子編程編程這個例子會輸出什么呢有些讀者朋友可能沒有想到其實上面的例子在不同的版本中運行會有不同的結果的那么接下來我們來試一下吧 我看到一個 segmentfault 上的問題, 是關于 String.intern() 的, 感覺比較有意思, 于是自己也去探索了一下, 有了一...

    siberiawolf 評論0 收藏0
  • 深入研究Java String

    摘要:所以我決定先從類入手,深入的研究一番來開個好頭。之所以會有以上的效果,是因為有字符串常量池的存在。同時運行時實例創建的全局字符串常量池中有一個表,總是為池中的每個字符串對象維護一個引用,所以這些對象不會被。 開始寫 Java 一年來,一直都是遇到什么問題再去解決,還沒有主動的深入的去學習過 Java 語言的特性和深入閱讀 JDK 的源碼。既然決定今后靠 Java吃飯,還是得花些心思在上...

    番茄西紅柿 評論0 收藏0
  • Java內存區域及內存溢出

    摘要:直接通過可以造成本機內存溢出。小節內存區域描述異常程序計數器略略略虛擬機棧存放編譯器可知的各種基本類型,對象引用和類型每個線程的棧大小堆存放對象實例最大值最小值運行時常亮池存放編譯期生成的字面量和符號引用,運行期也能放入常量池。 堆溢出 Java堆用于存儲對象實例,只要不斷地創建對象,并且保證GC Roots到對象之間有可達路徑避免垃圾回收,當到達最大堆的容量限制后就會產生Java.l...

    cheukyin 評論0 收藏0
  • 為什么不建議在for循環中使用"+"進行字符串拼接

    摘要:使用可以方便的對字符串進行拼接。該方法使用進行聲明,說明是一個線程安全的方法。所以,阿里巴巴開發手冊建議循環體內,字符串的連接方式,使用的方法進行擴展。但是,還要強調的是如果不是在循環體中進行字符串拼接的話,直接使用就好了。 摘要: 學習阿里巴巴Java開發手冊。 原文:為什么阿里巴巴不建議在for循環中使用+進行字符串拼接 微信公眾號:Hollis Fundebug經授權轉載,...

    caoym 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<