目錄:
Java語法糖系列一:可變長度參數和foreach循環
http://www.lxweimin.com/p/628568f94ef8
Java語法糖系列二:自動裝箱/拆箱和條件編譯
http://www.lxweimin.com/p/946b3c4a5db6
Java語法糖系列三:泛型與類型擦除
http://www.lxweimin.com/p/4de08deb6ba4
Java語法糖系列四:枚舉類型
http://www.lxweimin.com/p/ae09363fe734
Java語法糖系列五:內部類和閉包
http://www.lxweimin.com/p/f55b11a4cec2
上一篇寫到可變長參數和foreach循環,這篇討論下java的自動裝箱/拆箱和條件編譯這兩個語法糖。
自動裝箱/拆箱
自動拆箱/裝箱是在編譯期,依據代碼的語法,決定是否進行拆箱和裝箱動作。
裝箱過程:把基本類型用它們對應的包裝類型進行包裝,使基本類型具有對象特征。
拆箱過程:與裝箱過程相反,把包裝類型轉換成基本類型。
public static void main(String[] args){
int i=1;
Integer a = 1;
Integer b = 1;
Long c = 1L;
System.out.println(a == b);
System.out.println(a.equals(i));
System.out.println(c.equals(a));
}
結果是
true
true
false
編譯出來的代碼如下
public static void main(String[] paramArrayOfString)
{
int i = 1;
Integer localInteger1 = Integer.valueOf(1);
Integer localInteger2 = Integer.valueOf(1);
Long localLong = Long.valueOf(1L);
System.out.println(localInteger1 == localInteger2);
System.out.println(localInteger1.equals(Integer.valueOf(i)));
System.out.println(localLong.equals(localInteger1));
}
可以看到在自動裝箱的時候,Java虛擬機會自動調用Integer的valueOf方法;
在自動拆箱的時候,Java虛擬機會自動調用Integer的intValue方法。這就是自動拆箱和自動裝箱的原理。
注:上述例子的代碼應該盡量避免自動拆箱與裝箱。
條件編譯
很多編程語言都提供了條件編譯的途徑,C,C++中使用#ifdef。
看如下C代碼,在debug模式編譯代碼塊1,其他編譯代碼塊2
#define DEBUG
#IFDEF DEBUUG
/*
code block 1
*/
#ELSE
/*
code block 2
*/
#ENDIF
Java語言并沒有提供這種預編譯功能,但是Java也能實現預編譯。
源代碼
public static void main(String[] args){
// TODO Auto-generated method stub
if(true){
System.out.println("true");
}else{
System.out.println("false");
}
}
編譯后的代碼
public static void main(String[] paramArrayOfString)
{
System.out.println("true");
}
可以看到編譯器會對代碼進行優化,對于條件永遠為false的語句,JAVA編譯器將不會對其生成字節碼。這一動作發生在編譯器解除語法糖階段。所以說,可以利用條件語句來實現預編譯。
至于運用當然是在bebug模式下打log啦
public static void main(String[] args){
// TODO Auto-generated method stub
boolean DEBUG=true;
if(DEBUG) {
log.info("Syntactic Sugar!");
}
}
一點拓展
看如下代碼
public static void main(String[] args){
// TODO Auto-generated method stub
Integer i1 = 127;
Integer i2 = 127;
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i1 == i2);
System.out.println(i3 == i4);
Double d1 = 127.0;
Double d2 = 127.0;
Double d3 = 128.0;
Double d4 = 128.0;
System.out.println(d1 == d2);
System.out.println(d3 == d4);
}
結果是
true
false
false
false
產生這樣的結果的原因是:Byte、Short、Integer、Long、Char這幾個裝箱類的valueOf()方法是以128位分界線做了緩存的,假如是[-128,127]區間的值是會取緩存里面的引用的,以Integer為例,其valueOf(int i)的源代碼為:
static final int low = -128;
static final int high=127;
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
而Float、Double不會的原因也很簡單,因為byte、Short、integer、long、char在某個范圍內的整數個數是有限的,但是float、double這兩個浮點數卻不是。