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

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

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

    Sky's blog

    我和我追逐的夢(mèng)

    常用鏈接

    統(tǒng)計(jì)

    其他鏈接

    友情鏈接

    最新評(píng)論

    sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化

    首先把問題擺出來(lái),先看這個(gè)代碼

    String a = "ab";
    String b = "a" + "b";
    System.out.println((a == b));

    打印結(jié)果會(huì)是什么?類似這樣的問題,有人考過我,我也拿來(lái)考過別人(蠻好玩的,大家也可以拿來(lái)問人玩),一般答案會(huì)是以下幾種:

    1.true
    "a" + "b" 的結(jié)果就是"ab",這樣a,b都是"ab"了,內(nèi)容一樣所以"相等",結(jié)果true
    一般java新人如是答。
    2.false
    "a" + "a"會(huì)生成新的對(duì)象"aa",但是這個(gè)對(duì)象和String a = "ab";不同,(a == b)是比較對(duì)象引用,因此不相等,結(jié)果false
    對(duì)java的String有一定了解的通常這樣回答。
    3.true
    String a = "ab";創(chuàng)建了新的對(duì)象"ab"; 再執(zhí)行String b = "a" + "b";結(jié)果b="ab",這里沒有創(chuàng)建新的對(duì)象,而是從JVM字符串常量池中獲取之前已經(jīng)存在的"ab"對(duì)象。因此a,b具有對(duì)同一個(gè)string對(duì)象 的引用,兩個(gè)引用相等,結(jié)果true.
    能回答出這個(gè)答案的,基本已經(jīng)是高手了,對(duì)java中的string機(jī)制比較了解。
    很遺憾,這個(gè)答案,是不夠準(zhǔn)確的。或者說(shuō),根本沒有運(yùn)行時(shí)計(jì)算b = "a" + "b";這個(gè)操作.實(shí)際上運(yùn)行時(shí)只有String b = "ab";
    3的觀點(diǎn)適合解釋以下情況:
    String a = "ab";
    String b = "ab";
    System.out.println((a == b));
    如果String b = "a" + "b";是在運(yùn)行期執(zhí)行,則3的觀點(diǎn)是無(wú)法解釋的。運(yùn)行期的兩個(gè)string相加,會(huì)產(chǎn)生新的對(duì)象的。(本文后面對(duì)此有解釋)

    4.true
    下面是我的回答:編譯優(yōu)化+ 3的處理方式 = 最后的true
    String b = "a" + "b";編譯器將這個(gè)"a" + "b"作為常量表達(dá)式,在編譯時(shí)進(jìn)行優(yōu)化,直接取結(jié)果"ab",這樣這個(gè)問題退化
    String a = "ab";
    String b = "ab";
    System.out.println((a == b));
    然后根據(jù)3的解釋,得到結(jié)果true

    這里有一個(gè)疑問就是String不是基本類型,像
    int secondsOfDay = 24 * 60 * 60;
    這樣的表達(dá)式是常量表達(dá)式,編譯器在編譯時(shí)直接計(jì)算容易理解,而"a" + "b" 這樣的表達(dá)式,string是對(duì)象不是基本類型,編譯器會(huì)把它當(dāng)成常量表達(dá)式來(lái)優(yōu)化嗎?
    下面簡(jiǎn)單證明我的推斷,首先編譯這個(gè)類:
    public class Test {
    private String a = "aa";
    }
    復(fù)制class文件備用,然后修改為
    public class Test {
    private String a = "a" + "a";
    }
    再次編譯,用ue之類的文本編輯器打開,察看二進(jìn)制內(nèi)容,可以發(fā)現(xiàn),兩個(gè)class文件完全一致,連一個(gè)字節(jié)都不差.
    ok,真相大白了.根本不存在運(yùn)行期的處理String b = "a" + "b";這樣的代碼的問題,編譯時(shí)就直接優(yōu)化掉了。

    下面進(jìn)一步探討,什么樣的string + 表達(dá)式會(huì)被編譯器當(dāng)成常量表達(dá)式?
    String b = "a" + "b";
    這個(gè)String + String被正式是ok的,那么string + 基本類型呢?

    String a = "a1";
    String b = "a" + 1;
    System.out.println((a == b)); //result = true

    String a = "atrue";
    String b = "a" + true;
    System.out.println((a == b)); //result = true

    String a = "a3.4";
    String b = "a" + 3.4;
    System.out.println((a == b)); //result = true

    可見編譯器對(duì)string + 基本類型是當(dāng)成常量表達(dá)式直接求值來(lái)優(yōu)化的。

    再注意看這里的string都是"**"這樣的,我們換成變量來(lái)試試:
    String a = "ab";
    String bb = "b";
    String b = "a" + bb;
    System.out.println((a == b)); //result = false
    這個(gè)好理解,"a" + bb中的bb是變量,不能進(jìn)行優(yōu)化。這里很很好的解釋了為什么3的觀點(diǎn)不正確,如果String+String的操作是在運(yùn)行時(shí)進(jìn)行的,則會(huì)產(chǎn)生新的對(duì)象,而不是直接從jvm的string池中獲取。

    再修改一下,把bb作為常量變量:
    String a = "ab";
    final String bb = "b";
    String b = "a" + bb;
    System.out.println((a == b)); //result = true
    竟然又是true,編譯器的優(yōu)化好厲害啊,呵呵,考慮下面這種情況:
    String a = "ab";
    final String bb = getBB();
    String b = "a" + bb;
    System.out.println((a == b)); //result = false
    private static String getBB() {
    return "b";
    }
    看來(lái)java(包括編譯器和jvm)對(duì)string的優(yōu)化,真的是到了極點(diǎn)了,string這個(gè)所謂的"對(duì)象",完全不可以看成一般的對(duì)象,java對(duì)string的處理近乎于基本類型,最大限度的優(yōu)化了幾乎能優(yōu)化的地方。不過只在sun的java編譯器下測(cè)試過,還不清楚其他的java編譯器是否會(huì)同樣處理, 平時(shí)開發(fā)不接觸,懶得去研究了.

    另外感嘆一下,string的+號(hào)處理,算是java語(yǔ)言里面唯一的一個(gè)"運(yùn)算符重載"(接觸過c++的人對(duì)這個(gè)不會(huì)陌生)吧?

    posted on 2007-12-05 15:42 sky ao 閱讀(2612) 評(píng)論(16)  編輯  收藏 所屬分類: java

    評(píng)論

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2007-12-05 16:46 寒松

    牛,增長(zhǎng)了知識(shí)。
    但不知道是否做過測(cè)試,在那個(gè)版本的jdk編譯才會(huì)有這樣的情況?我相信這樣的編譯優(yōu)化是和版本有關(guān)的  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2007-12-05 16:56 飄然

    只在sun的java編譯器下測(cè)試過,還不清楚其他的java編譯器是否會(huì)同樣處理, 平時(shí)開發(fā)不接觸其他版本的java編譯器。  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2007-12-05 17:10 Edward's

    真牛!  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2007-12-05 19:35 mg12

    受教了.  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2007-12-05 21:27 cccp21

    牛!

    寒松問的版本應(yīng)該是指sun的多少版本——1.4?1.5?1.6?  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2007-12-05 22:31 Matthew Chen

    最后的這個(gè)方法:
    private static String getBB() {
    return "b";
    }
    如果加上final應(yīng)該會(huì)內(nèi)聯(lián)吧,說(shuō)不定還是可以的哦。  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2007-12-05 23:24 隔葉黃鶯

    String b = "a" + "b";
    這種優(yōu)化功能一般編譯器都會(huì)具備的,用javap -c HelloWorld 就能看到生成的代碼

    好點(diǎn)的編譯器都會(huì)把 b = a * 8;編譯成 b = a<<3; 甚至把 a * 9 編譯成 a<<3+a

    說(shuō)到
    String a = "ab";
    final String bb = "b"; 就是編譯器的內(nèi)聯(lián)了、靜態(tài)聯(lián)編了。其實(shí)做java的不用太去關(guān)心這些問題,我一個(gè)做硬件的同學(xué)都說(shuō)了,你們現(xiàn)在那些寫程序都不考慮內(nèi)存,什么程序都這么占內(nèi)存。其實(shí)我的關(guān)點(diǎn)是順手能做好的盡量做好,何必所有的事情都推向GC呢,我Review別人的代碼發(fā)現(xiàn)他們?nèi)?new Long(0),而不是 Long.value(0) 來(lái)生成 Long 對(duì)象的。

    看我原來(lái)寫過這樣一個(gè)東西:拾談"用最有效率的方法算出2乘以8等於幾?" http://www.tkk7.com/Unmi/articles/124098.html,其實(shí)很無(wú)聊的。

    原來(lái)聽說(shuō)過幾個(gè)俄羅斯的程序員往一個(gè)硬件上寫程序,容量太小,用匯編也擠不下去,后來(lái)就直接用 HEX 代碼來(lái)寫了。  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2007-12-06 10:22 千里冰封

    太牛了  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2007-12-08 05:57 roygbip

    好文,受教!  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化[未登錄] 2007-12-29 17:17 菜鳥

    真正的高手。多謝!  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2008-01-15 10:24 愛上鳥的魚

    學(xué)習(xí)!感謝!  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2009-07-09 09:51 小人物

    學(xué)習(xí)了。真是好文章!  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化[未登錄] 2009-07-22 22:38 YODA

    研究的很有意思,看來(lái)是花了心思琢磨了
    不過,通常情況下我們不會(huì)真正的去寫一些對(duì)編譯器優(yōu)化這么依賴的代碼.  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2009-09-10 17:34 三人行,必有我?guī)熝?/a>

    String a = "ab";
    String b = "a" + "b";
    String c = "a";
    String d = "b";
    String e = c + d;
    System.out.println( ( a == b ) );
    System.out.println( ( a == e ) );

    呵呵,看看結(jié)果……  
    回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2009-11-08 22:56 martree

    請(qǐng)問
    “a”.toLowerCase()=="a"//true
    "a"+"b".toLowerCase()=="ab"//false
    如何解釋,編譯器如何做的優(yōu)化  回復(fù)  更多評(píng)論   

    # re: sun的java編譯器對(duì)string常量表達(dá)式的處理和優(yōu)化 2009-11-10 10:15 sky ao

    “a”.toLowerCase()=="a"//true
    "a"+"b".toLowerCase()=="ab"//false

    這里沒有什么編譯器優(yōu)化的問題,toLowerCase()是方法調(diào)用,其結(jié)果在運(yùn)行期展開,編譯時(shí)沒有優(yōu)化可言。

    1. 先看String.toLowerCase()方法,這個(gè)方法有個(gè)特殊的地方,如果字符串在調(diào)用之后內(nèi)容沒有修改,則只是簡(jiǎn)單的返回原有字符串的對(duì)象應(yīng)用,而不是新建一個(gè)同樣內(nèi)容的字符串。
    在你的例子中,運(yùn)行時(shí)“a”.toLowerCase()返回的還是"a"的對(duì)象引用。

    3. "a"+"b".toLowerCase()的解釋就是這個(gè)表達(dá)式在運(yùn)行期執(zhí)行
    "a"+"b".toLowerCase() -> "a" + "b" -> "ab" ,注意"a" + "b"實(shí)在運(yùn)行期執(zhí)行,因此會(huì)產(chǎn)生一個(gè)新的字符串  回復(fù)  更多評(píng)論   

    主站蜘蛛池模板: 麻豆亚洲av熟女国产一区二| 四虎永久免费影院| 亚洲AV成人片色在线观看高潮 | 亚洲免费视频播放| 久久狠狠高潮亚洲精品 | 亚洲一卡二卡三卡四卡无卡麻豆| 日本黄网站动漫视频免费| 中文字幕无码免费久久9一区9 | 亚洲国产成人无码AV在线影院| 国产精品免费视频播放器| 午夜成人无码福利免费视频| 国产亚洲精品资源在线26u| 久久久久av无码免费网| 国产激情免费视频在线观看 | 18女人腿打开无遮掩免费| 亚洲综合欧美色五月俺也去| 亚洲精品456播放| 免费国产99久久久香蕉| 亚洲精品人成网在线播放影院| 亚洲不卡无码av中文字幕| 久99久精品免费视频热77| 亚洲精品无码专区| 国产亚洲色婷婷久久99精品| 国产国拍亚洲精品福利 | 亚洲成人一区二区| 国产猛烈高潮尖叫视频免费 | 在线观看亚洲专区| 亚洲国产三级在线观看| 亚洲一级Av无码毛片久久精品| 无码不卡亚洲成?人片| 69视频在线观看免费| 成人免费网站视频www| 特级毛片全部免费播放a一级| 亚洲欧洲精品久久| 成人毛片免费观看视频在线| 两个人看的www高清免费观看| 亚洲色大成WWW亚洲女子| 亚洲色成人网站WWW永久四虎| 亚洲中文字幕精品久久| 亚洲另类无码专区丝袜| 国产成人精品日本亚洲语音|