目錄:
Java語法糖系列一:可變長度參數(shù)和foreach循環(huán)
http://www.reibang.com/p/628568f94ef8
Java語法糖系列二:自動裝箱/拆箱和條件編譯
http://www.reibang.com/p/946b3c4a5db6
Java語法糖系列三:泛型與類型擦除
http://www.reibang.com/p/4de08deb6ba4
Java語法糖系列四:枚舉類型
http://www.reibang.com/p/ae09363fe734
Java語法糖系列五:內(nèi)部類和閉包
http://www.reibang.com/p/f55b11a4cec2
上一篇寫到可變長參數(shù)和foreach循環(huán),這篇討論下java的自動裝箱/拆箱和條件編譯這兩個語法糖。
自動裝箱/拆箱
自動拆箱/裝箱是在編譯期驯绎,依據(jù)代碼的語法肌蜻,決定是否進(jìn)行拆箱和裝箱動作黎泣。
裝箱過程:把基本類型用它們對應(yīng)的包裝類型進(jìn)行包裝,使基本類型具有對象特征腰素。
拆箱過程:與裝箱過程相反聘裁,把包裝類型轉(zhuǎn)換成基本類型。
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));
}
結(jié)果是
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虛擬機(jī)會自動調(diào)用Integer的valueOf方法衡便;
在自動拆箱的時候,Java虛擬機(jī)會自動調(diào)用Integer的intValue方法洋访。這就是自動拆箱和自動裝箱的原理镣陕。
注:上述例子的代碼應(yīng)該盡量避免自動拆箱與裝箱。
條件編譯
很多編程語言都提供了條件編譯的途徑姻政,C呆抑,C++中使用#ifdef。
看如下C代碼汁展,在debug模式編譯代碼塊1鹊碍,其他編譯代碼塊2
#define DEBUG
#IFDEF DEBUUG
/*
code block 1
*/
#ELSE
/*
code block 2
*/
#ENDIF
Java語言并沒有提供這種預(yù)編譯功能,但是Java也能實(shí)現(xiàn)預(yù)編譯食绿。
源代碼
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");
}
可以看到編譯器會對代碼進(jìn)行優(yōu)化侈咕,對于條件永遠(yuǎn)為false的語句,JAVA編譯器將不會對其生成字節(jié)碼器紧。這一動作發(fā)生在編譯器解除語法糖階段耀销。所以說,可以利用條件語句來實(shí)現(xiàn)預(yù)編譯铲汪。
至于運(yùn)用當(dāng)然是在bebug模式下打log啦
public static void main(String[] args){
// TODO Auto-generated method stub
boolean DEBUG=true;
if(DEBUG) {
log.info("Syntactic Sugar熊尉!");
}
}
一點(diǎn)拓展
看如下代碼
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);
}
結(jié)果是
true
false
false
false
產(chǎn)生這樣的結(jié)果的原因是:Byte、Short掌腰、Integer狰住、Long、Char這幾個裝箱類的valueOf()方法是以128位分界線做了緩存的齿梁,假如是[-128,127]區(qū)間的值是會取緩存里面的引用的转晰,以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不會的原因也很簡單查邢,因?yàn)閎yte、Short酵幕、integer扰藕、long、char在某個范圍內(nèi)的整數(shù)個數(shù)是有限的芳撒,但是float邓深、double這兩個浮點(diǎn)數(shù)卻不是未桥。