成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

關(guān)于String.intern()和new StringBuilder("").

derek_334892 / 3836人閱讀

摘要:對(duì)比較返回是因?yàn)檫@個(gè)字符串在執(zhí)之前已經(jīng)出現(xiàn)過,字符串常量池中已經(jīng)有它的引用了,不符合首次出現(xiàn)的原則,而計(jì)算機(jī)軟件這個(gè)字符串則是首次出現(xiàn)的,因此返回。

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

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

}

運(yùn)行結(jié)果:true false
書中給的解釋是:

JDK 1.7(以及部分其他虛擬機(jī),例如JRockit)的intern()實(shí)現(xiàn)不會(huì)再?gòu)?fù)制實(shí)例,只是在常量池中記錄首次出現(xiàn)的實(shí)例引用,因此intern()返回的引用和由StringBuilder創(chuàng)建的那個(gè)字符串實(shí)例是同一個(gè)。對(duì)str2比較返回false是因?yàn)椤癹ava”這個(gè)字符串在執(zhí)StringBuilder.toString()之前已經(jīng)出現(xiàn)過,字符串常量池中已經(jīng)有它的引用了,不符合“首次出現(xiàn)”的原則,而“計(jì)算機(jī)軟件”這個(gè)字符串則是首次出現(xiàn)的,因此返回true。

現(xiàn)在的疑問是“java”這個(gè)字符串在常量池中什么時(shí)候存在了?
我最開始的猜想是“java”這個(gè)字符串是不是常駐在常量池中的?那為什么常駐在常量池中呢?Java虛擬機(jī)什么時(shí)候加載了“java”這個(gè)字符串?

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

java虛擬機(jī)會(huì)自動(dòng)調(diào)用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類中的注釋可以知道,調(diào)用了initializeSystemClass方法,在此方法中調(diào)用了Version對(duì)象的init靜態(tài)方法
sun.misc.Version.init();
因此sun.misc.Version類會(huì)在JDK類庫(kù)的初始化過程中被加載并初始化。
查看Version類定義的私有靜態(tài)字符串常量如下:
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類時(shí),對(duì)其靜態(tài)常量字段根據(jù)指定的常量值做默認(rèn)初始化,所以"java"被加載到了字符串常量池中,修改上面代碼使字符串值為上面常量中的任意一個(gè)都會(huì)返回false。
String str2=new StringBuilder("1.7.0").append("_51").toString();
System.out.println(str2.intern()==str2);

這個(gè)問題解決了,然后我又發(fā)現(xiàn)了另外一個(gè)問題。除了這些在虛擬機(jī)加載時(shí)就初始化的常量,定義其他的字符串常量,比如“nihao”.

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

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

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67760.html

相關(guān)文章

  • String的內(nèi)存模型,為什么String被設(shè)計(jì)成不可變的

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

    vspiders 評(píng)論0 收藏0
  • 關(guān)于 String.intern() 的思考

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

    siberiawolf 評(píng)論0 收藏0
  • 深入研究Java String

    摘要:所以我決定先從類入手,深入的研究一番來開個(gè)好頭。之所以會(huì)有以上的效果,是因?yàn)橛凶址A砍氐拇嬖?。同時(shí)運(yùn)行時(shí)實(shí)例創(chuàng)建的全局字符串常量池中有一個(gè)表,總是為池中的每個(gè)字符串對(duì)象維護(hù)一個(gè)引用,所以這些對(duì)象不會(huì)被。 開始寫 Java 一年來,一直都是遇到什么問題再去解決,還沒有主動(dòng)的深入的去學(xué)習(xí)過 Java 語言的特性和深入閱讀 JDK 的源碼。既然決定今后靠 Java吃飯,還是得花些心思在上...

    番茄西紅柿 評(píng)論0 收藏0
  • Java內(nèi)存區(qū)域及內(nèi)存溢出

    摘要:直接通過可以造成本機(jī)內(nèi)存溢出。小節(jié)內(nèi)存區(qū)域描述異常程序計(jì)數(shù)器略略略虛擬機(jī)棧存放編譯器可知的各種基本類型,對(duì)象引用和類型每個(gè)線程的棧大小堆存放對(duì)象實(shí)例最大值最小值運(yùn)行時(shí)常亮池存放編譯期生成的字面量和符號(hào)引用,運(yùn)行期也能放入常量池。 堆溢出 Java堆用于存儲(chǔ)對(duì)象實(shí)例,只要不斷地創(chuàng)建對(duì)象,并且保證GC Roots到對(duì)象之間有可達(dá)路徑避免垃圾回收,當(dāng)?shù)竭_(dá)最大堆的容量限制后就會(huì)產(chǎn)生Java.l...

    cheukyin 評(píng)論0 收藏0
  • 為什么不建議在for循環(huán)中使用"+"進(jìn)行字符串拼接

    摘要:使用可以方便的對(duì)字符串進(jìn)行拼接。該方法使用進(jìn)行聲明,說明是一個(gè)線程安全的方法。所以,阿里巴巴開發(fā)手冊(cè)建議循環(huán)體內(nèi),字符串的連接方式,使用的方法進(jìn)行擴(kuò)展。但是,還要強(qiáng)調(diào)的是如果不是在循環(huán)體中進(jìn)行字符串拼接的話,直接使用就好了。 摘要: 學(xué)習(xí)阿里巴巴Java開發(fā)手冊(cè)。 原文:為什么阿里巴巴不建議在for循環(huán)中使用+進(jìn)行字符串拼接 微信公眾號(hào):Hollis Fundebug經(jīng)授權(quán)轉(zhuǎn)載,...

    caoym 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<