Java语法糖(Syntactic Sugar)之一--自动装箱/拆箱

1.语法糖

要说语法糖,首先要知道语法糖的含义.我们看百度百科中的定义,语法糖(Syntactic sugar),也译为糖衣语法,

是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,

这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会.

在JDK1.5之后,增加了很多语法糖,常用的如泛型,变长参数,自动装箱/拆箱,遍历循环(foreach).

今天,我们说一下语法糖之一自动装箱拆箱的梗.

2.语法糖之一--自动装箱/拆箱

在Java语言中,自动装箱(autoBoxing)是指将基本的数据类型(byte,short,char,int,long,float,double,boolean)

转换成对应的封装类(Byte,Short,Character,Integer,Long,Float,Double,Boolean),拆箱(unboxing)过程则是把

对应的封装类对象还原成基本数据类型的过程,是我们常用的语法糖之一.

今天我们以java中字节码的形式去解释一些在自动装箱/拆箱中常见易答错问题.

例1:

Integer a = 1;

Integer b = 1;

那么,打印a==b返回什么?

我们通过字节码+源码的形式去分析自动装箱.

首先,Integer a = 1的自动装箱过程是在编译器将".java"代码编译成".class"过程中进行的.

在字节码中,我们可以清楚的看到,自动装箱过程是使用了Integer类中的静态方法valueOf(int i),它的参数是一个int值,返回类型是Integer对象.见图.

我们去Integer类中找到该方法,看下源码中是怎么做的.见图.

 

 

在源码中,我们可以看到,Integer将-128~127之间的Integer对象都缓存在了私有静态内部类IntegerCache的静态常量数组cache[]中.如果超出此范围,则需要新创建Integer对象.

也就是说,在-128~127范围内的数值,自动装箱成包装类Integer后,指向的是同一个内容.

我们知道,方法中的局部变量是放在Java虚拟机栈栈帧的局部变量表中,而常量是放在方法区的.所以,此时,局部变量表中的引用类型a和b都指向了方法区中的cache[1+128]位置.所以,我们可以明确得出a==b打印出来是true.

例2:

Integer a = 257;

Integer b = 257;

那么,打印a==b返回什么?a.equals(b)呢?(此问题问过很多老鸟,答对着寥寥无几)

根据例1中的源码分析,我们可以知道,超过-128~127范围内的数值,在自动装箱时候,会新创建Integer对象,而对象的创建是在堆中完成的.因此,此时栈帧中引用类型a,b指向的是两个对象(引用类型中存放的是对象的地址或者句柄地址).所以,我们可以明确得出a==b打印是false.

对于a.equals(b),我们需要看一下Integer中equals源码部分.见图.


 

在源码中,我们可以清楚看到,在包装类对象比较使用equals时,当比较的对象是Integer的实例时,equals方法中做了拆箱操作,返回的是值与值的比较结果(257==257),所以,使用equals比较返回的结果a.equals(b)返回true.

如果不是Integer的实例,根据源码,直接返回false.

猜你喜欢

转载自zhaodengfeng1989.iteye.com/blog/2409773