前言
為什么會寫著篇博客,因為昨天看了關于final關鍵字的解析。但是有個問題始終沒有得到解決,于是請教了我qq上之前添加的知乎大神。他給我回復的第一條消息:常量折疊。身為渣渣猿的我立馬查詢了這個概念。這是第一次知道這個概念。知乎大神還給我講了好多。讓我終于明白了這個常量折疊的概念
所謂常量折疊是Java在編譯期間做的一個優化,簡單的來說就是在編譯期就把一些表達式計算好,不需要在運行時進行計算。
下面話不多說了,來一起看看詳細的介紹吧
實例解析
昨天,讓我迷惑的代碼是下面這段代碼
public static void main(String[] args) { String a = "hello2"; final String b = "hello"; String d = "hello"; String c = b + 2; String e = d + 2; System.out.println((a == c)); System.out.println((a == e)); }
這段的執行結果是
true
false
我就是不明白為什么第一個返回true呢?
留著這個疑問,我們先了解下常量折疊的概念。來更好的理解上面的代碼
常量折疊
常量折疊的概念
對于 String s1 = "1" + "2";
編譯器會給你優化成 String s1 = "12";
在生成的字節碼中,根本看不到 "1" "2" 這兩個東西。
我們通過idea進行驗證下
1、源碼文件
public static void main(String[] args) { String s1 = "1"+"2"; }
2、運行后,idea有個out文件夾,找到上面文件的class文件
public static void main(String[] args) { String s1 = "12"; }
確實如上面所說,編譯器會給你進行優化
常量折疊發生的條件
必須是編譯期常量之間進行運算才會進行常量折疊。
編譯期常量就是“編譯的時候就可以確定其值的常量”,
舉個栗子
1.第一個栗子
public static void main(String[] args) { String s1="a"+"bc"; String s2="ab"+"c"; System.out.println(s1 == s2); }
相信大家都知道了,輸出為true
并且只創建了一個 "abc" 字符串對象,且位于字符串常量池中。
2、第二個栗子
public static void main(String[] args) { String a = "a"; String bc = "bc"; String s1 = "a" + "bc"; String s2 = a + bc; System.out.println(s1 == s2); }
這個結果呢?false
s1 是字符串字面量相加,但是 s2 卻是兩個非 final 的變量相加,所以不會進行常量折疊。
而是根據 String 類特有的 + 運算符重載,變成類似這樣的代碼
String s2 = new StringBuffer(a).append(b).toString();
這里toString()會生成新的String變量,顯然用 == 運算符比較是會返回 false。
3、第三個栗子
public static void main(String[] args) { final String a = "a"; final String bc = "bc"; String s1 = "a" + "bc"; String s2 = a + bc; System.out.println(s1 == s2); }
這里的結果就是true
因為 被編譯器常量賦值的 final 的基本類型和字符串變量也是編譯期常量
4、第四個栗子
public static void main(String[] args) { String x ="a"; final String a = x; final String bc = "bc"; String s1 = "a" + "bc"; String s2 = a + bc; System.out.println(s1 == s2); }
這里的結果是false
這里需要注意的是:final的變量,不是被編譯期常量初始化的也不是編譯器常量
這里的a 就不是編譯器常量
總結
現在看完,是不是對上面打印的結果為什么是true 知道了呢?
所以。只要牢記常量折疊主要指的是編譯期常量加減乘除的運算過程會被折疊
好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。
新聞熱點
疑難解答
圖片精選