目录:
Java语法糖系列一:可变长度参数和foreach循环
http://www.jianshu.com/p/628568f94ef8
Java语法糖系列二:自动装箱/拆箱和条件编译
http://www.jianshu.com/p/946b3c4a5db6
Java语法糖系列三:泛型与类型擦除
http://www.jianshu.com/p/4de08deb6ba4
Java语法糖系列四:枚举类型
http://www.jianshu.com/p/ae09363fe734
Java语法糖系列五:内部类和闭包
http://www.jianshu.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这两个浮点数却不是。