java學(xué)習(xí)教程之常量折疊詳解
前言
為什么會(huì)寫著篇博客,因?yàn)樽蛱炜戳岁P(guān)于final關(guān)鍵字的解析。但是有個(gè)問題始終沒有得到解決,于是請(qǐng)教了我qq上之前添加的知乎大神。他給我回復(fù)的第一條消息:常量折疊。身為渣渣猿的我立馬查詢了這個(gè)概念。這是第一次知道這個(gè)概念。知乎大神還給我講了好多。讓我終于明白了這個(gè)常量折疊的概念
所謂常量折疊是Java在編譯期間做的一個(gè)優(yōu)化,簡(jiǎn)單的來說就是在編譯期就把一些表達(dá)式計(jì)算好,不需要在運(yùn)行時(shí)進(jìn)行計(jì)算。
下面話不多說了,來一起看看詳細(xì)的介紹吧
實(shí)例解析
昨天,讓我迷惑的代碼是下面這段代碼
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));
}
這段的執(zhí)行結(jié)果是
true
false
我就是不明白為什么第一個(gè)返回true呢?
留著這個(gè)疑問,我們先了解下常量折疊的概念。來更好的理解上面的代碼
常量折疊
常量折疊的概念
- 常量折疊是一種編譯器優(yōu)化技術(shù)。
- 常量折疊主要指的是編譯期常量加減乘除的運(yùn)算過程會(huì)被折疊
對(duì)于 String s1 = "1" + "2";
編譯器會(huì)給你優(yōu)化成 String s1 = "12";
在生成的字節(jié)碼中,根本看不到 "1" "2" 這兩個(gè)東西。
我們通過idea進(jìn)行驗(yàn)證下
1、源碼文件
public static void main(String[] args) {
String s1 = "1"+"2";
}
2、運(yùn)行后,idea有個(gè)out文件夾,找到上面文件的class文件
public static void main(String[] args) {
String s1 = "12";
}
確實(shí)如上面所說,編譯器會(huì)給你進(jìn)行優(yōu)化
常量折疊發(fā)生的條件
必須是編譯期常量之間進(jìn)行運(yùn)算才會(huì)進(jìn)行常量折疊。
編譯期常量就是“編譯的時(shí)候就可以確定其值的常量”,
- 首先:字面量是編譯期常量。(數(shù)字字面量,字符串字面量等)
- 其次:編譯期常量進(jìn)行簡(jiǎn)單運(yùn)算的結(jié)果也是編譯期常量,如1+2,"a"+"b"。
- 最后:被編譯器常量賦值的 final 的基本類型和字符串變量也是編譯期常量。
舉個(gè)栗子
1.第一個(gè)栗子
public static void main(String[] args) {
String s1="a"+"bc";
String s2="ab"+"c";
System.out.println(s1 == s2);
}
相信大家都知道了,輸出為true
并且只創(chuàng)建了一個(gè) "abc" 字符串對(duì)象,且位于字符串常量池中。
2、第二個(gè)栗子
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);
}
這個(gè)結(jié)果呢?false
s1 是字符串字面量相加,但是 s2 卻是兩個(gè)非 final 的變量相加,所以不會(huì)進(jìn)行常量折疊。
而是根據(jù) String 類特有的 + 運(yùn)算符重載,變成類似這樣的代碼
String s2 = new StringBuffer(a).append(b).toString();
這里toString()會(huì)生成新的String變量,顯然用 == 運(yùn)算符比較是會(huì)返回 false。
3、第三個(gè)栗子
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);
}
這里的結(jié)果就是true
因?yàn)?被編譯器常量賦值的 final 的基本類型和字符串變量也是編譯期常量
4、第四個(gè)栗子
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);
}
這里的結(jié)果是false
這里需要注意的是:final的變量,不是被編譯期常量初始化的也不是編譯器常量
這里的a 就不是編譯器常量
總結(jié)
現(xiàn)在看完,是不是對(duì)上面打印的結(jié)果為什么是true 知道了呢?
所以。只要牢記常量折疊主要指的是編譯期常量加減乘除的運(yùn)算過程會(huì)被折疊
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
使用java實(shí)現(xiàn)云端資源共享小程序的代碼
這篇文章主要介紹了用java寫一個(gè)云端資源共享小程序,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
Spring Cloud之注冊(cè)中心Nacos的使用詳解
本文介紹SpringCloud Alibaba中的Nacos組件,對(duì)比了Nacos與Eureka的區(qū)別,展示了如何在項(xiàng)目中引入SpringCloud Alibaba和Nacos,并配置負(fù)載均衡,通過實(shí)際操作,驗(yàn)證了服務(wù)注冊(cè)和負(fù)載均衡的功能,感興趣的朋友一起看看吧2025-03-03
Java實(shí)現(xiàn)輸出回環(huán)數(shù)(螺旋矩陣)的方法示例
這篇文章主要介紹了Java實(shí)現(xiàn)輸出回環(huán)數(shù)(螺旋矩陣)的方法,涉及java針對(duì)數(shù)組的遍歷、判斷、輸出等相關(guān)操作技巧,需要的朋友可以參考下2017-12-12
Java與Mysql鎖相關(guān)知識(shí)總結(jié)
這篇文章主要介紹了Java與Mysql鎖相關(guān)知識(shí)總結(jié)的相關(guān)資料,需要的朋友可以參考下2023-04-04
淺談SpringBoot集成Quartz動(dòng)態(tài)定時(shí)任務(wù)
這篇文章主要介紹了SpringBoot集成Quartz動(dòng)態(tài)定時(shí)任務(wù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
Java代碼實(shí)現(xiàn)哈希表(google 公司的上機(jī)題)
這篇文章主要介紹了Java 哈希表詳解(google 公司的上機(jī)題),本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03

