java編譯器對string常量運算式的處理和最佳化

來源:互聯網
上載者:User

標籤:

首先把問題擺出來,先看這個代碼 

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

列印結果會是什嗎?類似這樣的問題,有人考過我,我也拿來考過別人(蠻好玩的,大家也可以拿來問人玩),一般答案會是以下幾種: 

1.true 
    "a" + "b" 的結果就是"ab",這樣a,b都是"ab"了,內容一樣所以"相等",結果true 
    一般java新人如是答。 

2.false 

    "a" + "a"會產生新的對象"aa",但是這個對象和String a = "ab";不同,(a == b)是比較對象引用,因此不相等,結果false ,對java的String有一定瞭解的通常這樣回答。 

3.true 
    String a = "ab";建立了新的對象"ab"; 再執行String b = "a" + "b";結果b="ab",這裡沒有建立新的對象,而是從JVM字串常量池中擷取之前已經存在的"ab"對象。因此a,b具有對同一個string對象 的引用,兩個引用相等,結果true. 
    能回答出這個答案的,基本已經是高手了,對java中的string機制比較瞭解。 
    很遺憾,這個答案,是不夠準確的。或者說,根本沒有運行時計算b = "a" + "b";這個操作.實際上運行時只有String b = "ab"; 
    3的觀點適合解釋以下情況: 

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

    如果String b = "a" + "b";是在運行期執行,則3的觀點是無法解釋的。運行期的兩個string相加,會產生新的對象的。(本文後面對此有解釋) 

4.true 
    下面是我的回答:編譯最佳化+ 3的處理方式 = 最後的true 

    String b = "a" + "b";//編譯器將這個"a" + "b"作為常量運算式,在編譯時間進行最佳化,直接取結果"ab",這樣這個問題退化     String a = "ab";     String b = "ab";     System.out.println((a == b));

    然後根據3的解釋,得到結果true 
    這裡有一個疑問就是String不是基本類型,像 

    int secondsOfDay = 24 * 60 * 60;

    這樣的運算式是常量運算式,編譯器在編譯時間直接計算容易理解,而"a" + "b" 這樣的運算式,string是對象不是基本類型,編譯器會把它當成常量運算式來最佳化嗎? 
    下面簡單證明我的推斷,首先編譯這個類: 

public class Test {     private String a = "aa"; }

       複製class檔案備用,然後修改為 

public class Test {     private String a = "a" + "a"; }

    再次編譯,用ue之類的文字編輯器開啟,察看二進位內容,可以發現,兩個class檔案完全一致,連一個位元組都不差. 
    ok,真相大白了.根本不存在運行期的處理String b = "a" + "b";這樣的代碼的問題,編譯時間就直接最佳化掉了。 

下面進一步探討,什麼樣的string + 運算式會被編譯器當成常量運算式? 
String b = "a" + "b"; 
這個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

可見編譯器對string + 基本類型是當成常量運算式直接求值來最佳化的。 
再注意看這裡的string都是"**"這樣的,我們換成變數來試試: 

String a = "ab"; String bb = "b"; String b = "a" + bb; System.out.println((a == b));   //result = false

這個好理解,"a" + bb中的bb是變數,不能進行最佳化。這裡很很好的解釋了為什麼3的觀點不正確,如果String+String的操作是在運行時進行的,則會產生新的對象,而不是直接從jvm的string池中擷取。 
再修改一下,把bb作為常量變數: 

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

竟然又是true,編譯器的最佳化好厲害啊,呵呵,考慮下面這種情況: 

String a = "ab"; final String bb = getBB(); String b = "a" + bb; System.out.println((a == b));    //result = false private static String getBB() { return "b"; }

看來java(包括編譯器和jvm)對string的最佳化,真的是到了極點了,string這個所謂的"對象",完全不可以看成一般的對象,java對string的處理近乎於基本類型,最大限度的最佳化了幾乎能最佳化的地方。


java編譯器對string常量運算式的處理和最佳化

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.