语法糖(Syntactic Sugar),也叫糖衣语法,是英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语。指的是,在计算机语言中添加某种语法,这种语法能使程序员更方便的使用语言开发程序,同时增强程序代码的可读性,避免出错的机会;但是这种语法对语言的功能并没有影响。
Java中的泛型,变长参数,自动拆箱/装箱,条件编译等都是.
各种各样的语言都会提供一些语法糖来方便程序员开发,这些语法糖不会提供实质性的功能改进,但是能够提高效率.
Java的泛型语法是一种伪泛型,其实质是语法擦除,
看下代码:
public static void main(String[] args) {
Map map = new HashMap();
map.put("xiaoming","10");
map.put("baby","5");
System.out.println(map.get("xiaoming"));
System.out.println(map.get("baby"));
}
编译后生成的.class里代码被解语法糖之后:
public static void main(String[] args) {
HashMap map = new HashMap();
map.put("xiaoming", "10");
map.put("baby", "5");
System.out.println((String)map.get("xiaoming"));
System.out.println((String)map.get("baby"));
}
泛型实际上只存在于源代码里,编译后被解掉,所以泛型是java提供的一种语法糖.
Java泛型的设计是欠缺优雅的:
public static void generic(List list){
System.out.println("list = [" + list + "]");
}
public static void generic(List list){
System.out.println("list = [" + list + "]");
}
上面的代码是编译通过不了的.因为泛型是伪泛型,所以List和List都是List.
public static void main(String[] args) {
List list = Arrays.asList(1,2,3,4);
int sum = 0;
for (int i : list) {
sum += i;
}
System.out.println("sum = " + sum);
}
先上代码,上述代码包括泛型,装箱,拆箱,foreach,可变参数等几种语法糖,编译解语法糖后:
public static void main(String[] args) {
List list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4)});
int sum = 0;
int i;
for(Iterator i$ = list.iterator(); i$.hasNext(); sum += i) {
i = ((Integer)i$.next()).intValue();
}
System.out.println("sum = " + sum);
}
自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原始类型byte,short,char,int,long,float,double和boolean对应的封装类为Byte,Short,Character,Integer,Long,Float,Double,Boolean。
自动装箱和拆箱在Java中很常见,比如我们有一个方法,接受一个对象类型的参数,如果我们传递一个原始类型值,那么Java会自动讲这个原始类型值转换成与之对应的对象。最经典的一个场景就是当我们向ArrayList这样的容器中增加原始类型数据时或者是创建一个参数化的类,比如下面的ThreadLocal。
ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1); //autoboxing - primitive to object
intList.add(2); //autoboxing
ThreadLocal<Integer> intLocal = new ThreadLocal<Integer>();
intLocal.set(4); //autoboxing
int number = intList.get(0); // unboxing
int local = intLocal.get(); // unboxing in Java
解语法糖:
ArrayList intList1 = new ArrayList();
intList1.add(Integer.valueOf(1));
intList1.add(Integer.valueOf(2));
ThreadLocal intLocal1 = new ThreadLocal();
intLocal1.set(Integer.valueOf(4));
int number = ((Integer)intList1.get(0)).intValue();
int local = ((Integer)intLocal1.get()).intValue();
//—————-自动装箱 拆箱 场景
//-----------赋值
//before autoboxing
Integer i1 = Integer.valueOf(1000);
int j1 = i1.intValue();
//after java 5
Integer i2 = 1000;
int j2 = i2;
编译后:
int number = ((Integer)intList1.get(0)).intValue();
int local = ((Integer)intLocal1.get()).intValue();
Integer i1 = Integer.valueOf(1000);
int j1 = i1.intValue();
Integer i2 = Integer.valueOf(1000);
int j2 = i2.intValue();
//--------------调用
invoke(3); //autoboxing
编译后
invoke(Integer.valueOf(3));
public static Integer invoke(Integer i) {
return i;
}
//-------------自动装箱拆箱的陷阱
Integer sum1 = 0;
for (int i = 0; i < 1000; i++) {
sum1 += i;
}
System.out.println("sum1 = " + sum1);
编译后:
Integer sum1 = Integer.valueOf(0);
for(int i = 0; i < 1000; ++i) {
sum1 = Integer.valueOf(sum1.intValue() + i);
}
System.out.println("sum1 = " + sum1);
上面代码Integer.valueOf()会new出大量的无用对象严重影响程序的性能和gc.
在编码中应尽量避免.
//----------相等陷阱
int n1 = 127;
int n2 = 127;
System.out.println("n1==n2:" + (n1 == n2) );
int n3 = 1;
Integer n4 = 1;
System.out.println("n3==n4:" + (n3 == n4) );
Integer n5 = 127;
Integer n6 = 127;
System.out.println("n5==n6:" + (n5 == n6));
Integer n7 = 128;
Integer n8 = 128;
System.out.println("n7==n8:" + (n7 == n8)); //false
编译后:
byte var22 = 127;
byte n2 = 127;
System.out.println("n1==n2:" + (var22 == n2));
byte n3 = 1;
Integer n4 = Integer.valueOf(1);
System.out.println("n3==n4:" + (n3 == n4.intValue()));
Integer n5 = Integer.valueOf(127);
Integer n6 = Integer.valueOf(127);
System.out.println("n5==n6:" + (n5 == n6));
Integer n7 = Integer.valueOf(128);
Integer n8 = Integer.valueOf(128);
System.out.println("n7==n8:" + (n7 == n8));
Integer代码中:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
当数字在-128和127之间时会复用,之外时直接new.
//-----------初始化陷阱
Integer n9 = null;
int n10 = n9;
编译后:
Object n9 = null;
int n10 = ((Integer)n9).intValue();
上面代码引起空指针异常。
参考:
http://www.tuicool.com/articles/7ZZFfiy