<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    例子說明String的堆(heap)棧(stack)信息

         String是一個特殊的包裝類數(shù)據(jù)。即可以用String str = new String("abc");的形式來創(chuàng)建,也可以用String str = "abc";的形式來創(chuàng)建。前者是規(guī)范的類的創(chuàng)建過程,即在Java中,一切都是對象,而對象是類的實例,全部通過new()的形式來創(chuàng)建。Java 中的有些類,如DateFormat類,可以通過該類的getInstance()方法來返回一個新創(chuàng)建的類,似乎違反了此原則。其實不然。該類運用了單 例模式來返回類的實例,只不過這個實例是在該類內(nèi)部通過new()來創(chuàng)建的,而getInstance()向外部隱藏了此細節(jié)。那為什么在String str = "abc";中,并沒有通過new()來創(chuàng)建實例,是不是違反了上述原則?其實沒有。

      關(guān)于String str = "abc"的內(nèi)部工作。Java內(nèi)部將此語句轉(zhuǎn)化為以下幾個步驟:
    (1)先定義一個名為str的對String類的對象引用變量:String str;
    (2)在棧中查找有沒有存放值為"abc"的地址,如果沒有,則開辟一個存放字面值為"abc"的地址,接著創(chuàng)建一個新的String類的對象o,并 將o 的[url=]字符串[/url]值指向這個地址,而且在棧中這個地址旁邊記下這個引用的對象o。如果已經(jīng)有了值為"abc"的地址,則查找對象o,并返 回o的地址。
    (3)將str指向?qū)ο髈的地址。
    值得注意的是,一般String類中字符串值都是直接存值的。但像String str = "abc";這種場合下,其字符串值卻是保存了一個指向存在棧中數(shù)據(jù)的引用!
      
    為了更好地說明這個問題,我們可以通過以下的幾個代碼進行驗證。

    String str1 = "abc";
    String str2 = "abc";
    System.out.println(str1==str2);  //true
       
    注意,我們這里并不用str1.equals(str2);的方式,因為這將比較兩個字符串的值是否相等。==號,根據(jù)JDK的說明,只有在兩個引用都指向了同一個對象時才返回真值。而我們在這里要看的是,str1與str2是否都指向了同一個對象。
        圖解:
        
    結(jié)果說明,JVM創(chuàng)建了兩個引用str1和str2,但只創(chuàng)建了一個對象,而且兩個引用都指向了這個對象。

    我們再來更進一步,將以上代碼改成:

    String str1 = "abc";
    String str2 = "abc";
    str1 = "bcd";
    System.out.println(str1 + "," + str2);  //bcd, abc
    System.out.println(str1==str2);  //false

    這就是說,賦值的變化導致了類對象引用的變化,str1指向了另外一個新對象!而str2仍舊指向原來的對象。上例中,當我們將str1的值改為"bcd"時,JVM發(fā)現(xiàn)在棧中沒有存放該值的地址,便開辟了這個地址,并創(chuàng)建了一個新的對象,其字符串的值指向這個地址。
    事實上,String類被設(shè)計成為不可改變(immutable)的類。如果你要改變其值,可以,但JVM在運行時根據(jù)新值悄悄創(chuàng)建了一個新對象,然 后將這個對象的地址返回給原來類的引用。這個創(chuàng)建過程雖說是完全自動進行的,但它畢竟占用了更多的時間。在對時間要求比較敏感的環(huán)境中,會帶有一定的不良 影響。

    再修改原來代碼:

    String str1 = "abc";
    String str2 = "abc";
      
    str1 = "bcd";
      
    String str3 = str1;
    System.out.println(str3);  //bcd

    String str4 = "bcd";
    System.out.println(str1 == str4);  //true
       
       
    str3 這個對象的引用直接指向str1所指向的對象(注意,str3并沒有創(chuàng)建新對象)。當str1改完其值后,再創(chuàng)建一個String的引用str4,并指向 因str1修改值而創(chuàng)建的新的對象。可以發(fā)現(xiàn),這回str4也沒有創(chuàng)建新的對象,從而再次實現(xiàn)棧中數(shù)據(jù)的共享。

    我們再接著看以下的代碼。

    String str1 = new String("abc");
    String str2 = "abc";
    System.out.println(str1==str2);  //false



    創(chuàng)建了兩個引用。創(chuàng)建了兩個對象。兩個引用分別指向不同的兩個對象。

    String str1 = "abc";
    String str2 = new String("abc");
    System.out.println(str1==str2);  //false

    創(chuàng)建了兩個引用。創(chuàng)建了兩個對象。兩個引用分別指向不同的兩個對象。

    以上兩段代碼說明,只要是用new()來新建對象的,都會在堆中創(chuàng)建,而且其字符串是單獨存值的,即使與棧中的數(shù)據(jù)相同,也不會與棧中的數(shù)據(jù)共享。

    posted on 2008-09-04 14:22 nonels 閱讀(496) 評論(0)  編輯  收藏 所屬分類: J2SE

    <2008年9月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    導航

    統(tǒng)計

    常用鏈接

    留言簿(2)

    隨筆分類(16)

    隨筆檔案(16)

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲av无码专区在线观看下载 | 亚洲中文字幕无码一区| 国产免费爽爽视频在线观看| 中文字幕在线观看亚洲| 青青青国产免费一夜七次郎| fc2免费人成为视频| 亚洲视频免费在线看| 免费永久看黄在线观看app| 国产精品网站在线观看免费传媒| 亚洲一区二区三区深夜天堂| 亚洲AV中文无码乱人伦在线视色| 国产精品99久久免费观看| 亚洲大尺度无码无码专线一区| 亚洲av之男人的天堂网站| 成人最新午夜免费视频| 中文字幕免费在线观看动作大片| 亚洲一级大黄大色毛片| 在线亚洲97se亚洲综合在线| 性做久久久久久久免费看| 中文字幕免费观看视频| 亚洲欧美国产日韩av野草社区| 亚洲日韩av无码| 全部免费国产潢色一级| 午夜免费1000部| 在线观看免费无码专区| 国产精品亚洲片在线花蝴蝶| 亚洲成人黄色在线| 国产亚洲av人片在线观看| 四虎免费在线观看| 亚洲免费人成视频观看| 中国一级特黄的片子免费 | 免费精品国产日韩热久久| 久久久久女教师免费一区| 亚洲AV无码XXX麻豆艾秋| 久久精品亚洲一区二区三区浴池 | 亚洲国产精品久久久久婷婷老年| 亚洲高清成人一区二区三区| 最新中文字幕免费视频| 91高清免费国产自产拍2021| 久久精品无码免费不卡| 深夜久久AAAAA级毛片免费看|