编译器的两点优化
常量和變量的運(yùn)算
下面的程序有問(wèn)題嗎?
public static void main(String[] args){byte b1=1;byte b2=2;byte b3=1 + 2;byte b4=b1 + b2;System.out.println(b3);System.out.println(b4); }分析: b3 = 1 + 2 , 1 和 2 是常量,為固定不變的數(shù)據(jù),在編譯的時(shí)候(編譯器javac),已經(jīng)確定了1+2 的結(jié)果并沒(méi)有超過(guò)byte類型的取值范圍,可以賦值給變量b3 ,因此b3=1 + 2 是正確的。
反之, b4 = b2 + b3 , b2 和 b3 是變量,變量的值是可能變化的,在編譯的時(shí)候,編譯器javac不確定b2+b3的結(jié)果是什么,因此會(huì)將結(jié)果以int類型進(jìn)行處理,所以int類型不能賦值給byte類型,因此編譯失敗。
在jshell中體現(xiàn):
/* 對(duì)于byte/short/char三種類型來(lái)說(shuō),如果右側(cè)賦值的數(shù)值沒(méi)有超過(guò)范圍, 那么javac編譯器將會(huì)自動(dòng)隱含地為我們補(bǔ)上一個(gè)(byte)(short)(char)。1. 如果沒(méi)有超過(guò)左側(cè)的范圍,編譯器補(bǔ)上強(qiáng)轉(zhuǎn)。 2. 如果右側(cè)超過(guò)了左側(cè)范圍,那么直接編譯器報(bào)錯(cuò)。 */ public class Demo12Notice {public static void main(String[] args) {// 右側(cè)確實(shí)是一個(gè)int數(shù)字,但是沒(méi)有超過(guò)左側(cè)的范圍,就是正確的。// int --> byte,不是自動(dòng)類型轉(zhuǎn)換byte num1 = /*(byte)*/ 30; // 右側(cè)沒(méi)有超過(guò)左側(cè)的范圍System.out.println(num1); // 30// byte num2 = 128; // 右側(cè)超過(guò)了左側(cè)的范圍// int --> char,沒(méi)有超過(guò)范圍// 編譯器將會(huì)自動(dòng)補(bǔ)上一個(gè)隱含的(char)char zifu = /*(char)*/ 65;System.out.println(zifu); // A} } /* 在給變量進(jìn)行賦值的時(shí)候,如果右側(cè)的表達(dá)式當(dāng)中全都是常量,沒(méi)有任何變量, 那么編譯器javac將會(huì)直接將若干個(gè)常量表達(dá)式計(jì)算得到結(jié)果。 short result = 5 + 8; // 等號(hào)右邊全都是常量,沒(méi)有任何變量參與運(yùn)算 編譯之后,得到的.class字節(jié)碼文件當(dāng)中相當(dāng)于【直接就是】: short result = 13; 右側(cè)的常量結(jié)果數(shù)值,沒(méi)有超過(guò)左側(cè)范圍,所以正確。這稱為“編譯器的常量?jī)?yōu)化”。但是注意:一旦表達(dá)式當(dāng)中有變量參與,那么就不能進(jìn)行這種優(yōu)化了。 */ public class Demo13Notice {public static void main(String[] args) {short num1 = 10; // 正確寫(xiě)法,右側(cè)沒(méi)有超過(guò)左側(cè)的范圍,short a = 5;short b = 8;// short + short --> int + int --> int// short result = a + b; // 錯(cuò)誤寫(xiě)法!左側(cè)需要是int類型// 右側(cè)不用變量,而是采用常量,而且只有兩個(gè)常量,沒(méi)有別人short result = 5 + 8;System.out.println(result);short result2 = 5 + a + 8; // 18} }?
總結(jié)
- 上一篇: JDK9的JShell简单使用
- 下一篇: 流程概述与顺序结构