Java自动装箱与拆箱及其陷阱分析_第1页
Java自动装箱与拆箱及其陷阱分析_第2页
Java自动装箱与拆箱及其陷阱分析_第3页
Java自动装箱与拆箱及其陷阱分析_第4页
Java自动装箱与拆箱及其陷阱分析_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

本文格式为Word版,下载可任意编辑——Java自动装箱与拆箱及其陷阱分析Java自动装箱与拆箱及其陷阱分析

Java中一个分外重要也分外好玩的特性,就是自动装箱与拆箱,本文是我探寻整理的关于Java自动装箱与拆箱及其陷阱分析,给大家做个参考,梦想对大家有所扶助!想了解更多相关信息请持续关注我们我!

拆箱Unboxing

定义

Integerinteger100=100;

intint100=integer100;

从上面的代码中,大家可看出integer100为一个Integer类型的引用,int100为一个int类型的原始数据类型。但是,我们可以将一个Integer类型的对象赋值给其相应原始数据类型的变量。这便是拆箱。

拆箱与装箱是相反的操作。装箱是将一个原始数据类型赋值给相应封装类的变量。而拆箱那么是将一个封装类的变量赋值给相应原始数据类型的变量。装箱、拆箱的名字也取得相当贴切。

原理

笔者相信大家也都猜到了,拆箱过程中jdk为我们做了什么。我们还是通过测验来证明我们的揣摩吧。

在以上代码的其次行代码打上断点,即在"intint100=integer100;'上打上断点,跟踪一下。

我们可以看到,程序跳转到了Integer的intValue方法。

/**

*ReturnsthevalueofthiscodeInteger/codeasan

*codeint/code.

*/

publicintintValue

returnvalue;

也就是,jdk帮我们完成了对intValue方法的.调用。对于以上的测验而言,便是调用integer100的intValue方法,将其返回值赋给了int100。

扩展

测验1

Integerinteger400=400;

intint400=400;

System.out.printlninteger400==int400;

在以上代码的第三行中,integer400与int400执行了==运行。而这两个是不同类型的变量,毕竟是integer400拆箱了,还是int400装箱了呢?运行结果是什么呢?

==运算是判断两个对象的地址是否相等或者判断两个根基数据类型的值是否相等。所以,大家很轻易揣测到,假设integer400拆箱了,那么说明比较的是两个根基类型的值,那此时必然相等,运行结果为true;假设int400装箱了,那么说明比较的是两个对象的地址是否相等,那此时地址必然不相等,运行结果为false。(至于为什么笔者对它们赋值为400,就是后面将要讲到的陷阱有关)。

我们实际的运行结果为true。所以是integer400拆箱了。对代码跟踪的结果也证明这一点。

测验2

Integerinteger100=100;

intint100=100;

System.out.printlninteger100.equalsint100;

在以上代码的第三行中,integer100的方法equals的参数为int100。我们知道equals方法的参数为Object,而不是根基数据类型,因而在这里必然是int100装箱了。对代码跟踪的结果也证领略这一点。

其实,假设一个方法中参数类型为原始数据类型,所传入的参数类型为其封装类,那么会自动对其举行拆箱;相应地,假设一个方法中参数类型为封装类型,所传入的参数类型为其原始数据类型,那么会自动对其举行装箱。

测验3

Integerinteger100=100;

intint100=100;

Longlong200=200l;

System.out.printlninteger100+int100;

System.out.printlnlong200==integer100+int100;

System.out.printlnlong200.equalsinteger100+int100;

在第一个测验中,我们已经得知,当一个根基数据类型与封装类举行==运算时,会将封装类举行拆箱。那假设+、-、*、/呢?我们在这个测验中,就可知道。

假设+运算,会将根基数据类型装箱,那么:

?第4行中,integer100+int100就会得到一个类型为Integer且value为200的对象o,并执行这个对象的toString方法,并输出'200';

?第5行中,integer100+int100就会得到一个类型为Integer且value为200的对象o,==运算将这个对象与long200对象举行比较,鲜明,将会输出false;

?第6行中,integer100+int100就会得到一个类型为Integer且value为200的对象o,Long的equals方法将long200与o比较,由于两都是不同类型的封装类,因而输出false;

假设+运算,会将封装类举行拆箱,那么:

?第4行中,integer100+int100就会得到一个类型为int且value为200的根基数据类型b,再将b举行装箱得到o,执行这个对象的toString方法,并输出'200';

?第5行中,integer100+int100就会得到一个类型为int且value为200的根基数据类型b1,==运算将long200举行拆箱得到b2,鲜明b1==b2,输出true;

?第6行中,integer100+int100就会得到一个类型为int且value为200的根基数据类型b,Long的equals方法将b举行装箱,但装箱所得到的是类型为Integer的对象o,由于o与long200为不同的类型的对象,所以输出false;

程序运行的结果为:

200

true

false

因而,其次种揣测是正确,即在+运算时,会将封装类举行拆箱。

Java自动装箱与拆箱及其陷阱分析

陷阱

陷阱1

Integerinteger100=null;

intint100=integer100;

这两行代码是完全合法的,完全能够通过编译的,但是在运行时,就会抛出空指针奇怪。其中,integer100为Integer类型的对象,它当然可以指向null。但在其次行时,就会对integer100举行拆箱,也就是对一个null对象执行intValue方法,当然会抛出空指针奇怪。所以,有拆箱操作时确定要更加留神封装类对象是否为null。

陷阱2

Integeri1=100;

Integeri2=100;

Integeri3=300;

Integeri4=300;

System.out.printlni1==i2;

System.out.printlni3==i4;

由于i1、i2、i3、i4都是Integer类型的,所以我们想,运行结果理应都是false。但是,真实的运行结果为"System.out.printlni1==i2;'为true,但是"System.out.printlni3==i4;'为false。也就意味着,i1与i2这两个Integer类型的引用指向了同一个对象,而i3与i4指向了不同的对象。为什么呢?不都是调用Integer.valueOfinti方法吗?

让我们再看看Integer.valueOfinti方法。

/**

*ReturnsattInteger/ttinstancerepresentingthespecified

*ttint/ttvalue.

*IfanewttInteger/ttinstanceisnotrequired,thismethod

*shouldgenerallybeusedinpreferencetotheconstructor

*@link#Integerint,asthismethodislikelytoyield

*significantlybetterspaceandtimeperformancebycaching

*frequentlyrequestedvalues.

*

*@paramiancodeint/codevalue.

*@returnattInteger/ttinstancerepresentingtti/tt.

*@since1.5

*/

publicstaticIntegervalueOfinti

ifi=-128i=IntegerCache.high

returnIntegerCache.cache[i+128];

else

returnnewIntegeri;

我们可以看到当i=-128且i=IntegerCache.high时,直接返回IntegerCache.cache[i+128]。其中,IntegerCache为Integer的内部静态类,其原码如下:

privatestaticclassIntegerCache

staticfinalinthigh;

staticfinalIntegercache[];

static

finalintlow=-128;

//highvaluemaybeconfiguredbyproperty

inth=127;

ifintegerCacheHighPropValue!=null

//UseLong.decodeheretoavoidinvokingmethodsthat

//requireIntegersautoboxingcachetobeinitialized

inti=Long.decodeintegerCacheHighPropVValue;

i=Math.maxi,127;

//MaximumarraysizeisInteger.MAX_VALUE

h=Math.mini,Integer.MAX_VALUE--low;

high=h;

cache=newInteger[high-low+1];

intj=low;

forintk=0;kcache.length;k++

cache[k]=newIntegerj++;

privateIntegerCache

我们可以领会地看到,IntegerCache有静态成员变量cache,为一个拥有256个元素的数组。在IntegerCach

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论