本文主要介绍Java自动拆箱和自动装箱的相关知识。基本数据类型基本类型,或称内置类型,是Java中不同于类(Class)的特殊类型。它们是我们编程中最常用的类型。Java是一种强类型语言。变量的第一次声明必须指明数据类型,变量的第一次赋值称为变量初始化。Java有八种基本类型,可以分为三类:字符类型charboolean类型整型byte、short、int、long浮点型float、double。Java中没有无符号数值类型,它们的取值范围是固定的,不会随着机器硬件环境或操作系统的变化而改变。其实Java中还有一个基本类型void,它也有对应的包装类java.lang.Void,但是我们不能直接对它们进行操作。基本数据类型有什么好处我们都知道,在Java语言中,一个新的对象存放在堆中,我们通过栈中的引用来使用这些对象;因此,对象本身会消耗更多的资源。对于经常使用的类型,比如int等,如果我们每次使用这个变量都需要一个新的Java对象,会很麻烦。因此,和C++一样,Java提供了基本的数据类型。这个数据的变量不需要用new来创建。它们不会在堆上创建,而是直接存储在栈内存中,这样效率会更高。整数取值范围Java中的整数主要包括byte、short、int、long四种类型,表示的数字范围也是从小到大。之所以表示范围不同,主要是因为它们在存储数据个数相关时所占用的字节数。先来个简答科普,1byte=8bits(比特)。java中的整数是有符号数。我们先看看8bit在计算中可以表示的数:最小值:10000000(-128)(-2^7)***值:01111111(127)(2^7-1)这几种整数中,byte:byte以1个字节存储,范围从-128(-2^7)到127(2^7-1)。初始化变量时,字节类型默认值为0。short:short以2个字节存储,范围从-32,768(-2^15)到32,767(2^15-1)。变量初始化时,short类型的默认值为0,一般因为Java本身转换的原因,可以直接写成0。int:int以4个字节存储,范围从-2,147,483,648(-2^31)到2,147,483,647(2^31-1)。初始化变量时,int类型默认值为0。long:long以8个字节存储,范围从-9,223,372,036,854,775,808(-2^63)到9,223,372,036、854,775,807(2^63-1)。变量初始化时,long类型的默认值为0L或0l。直接写0。超出范围怎么办前面说过,在整型中,每种类型都有一定的表示范围,但是程序中的一些计算会导致超出表示范围,也就是溢出。比如下面的代码:inti=Integer.MAX_VALUE;intj=Integer.MAX_VALUE;intk=i+j;System.out.println("i("+i+")+j("+j+")=k("+k+")");输出结果:i(2147483647)+j(2147483647)=k(-2)这说明发生了溢出,发生溢出时不会抛出异常,也没有提示。因此,在程序中,使用同一类型的数据进行计算时,一定要注意数据溢出的问题。封装类型Java语言是一种面向对象的语言,但是Java中的基本数据类型并不是面向对象的,这在实际使用中有很多不便。为了解决这个问题,每一种基本数据类型都设计了一个对应的类来表示,所以把基本数据类型对应的八个类统称为包装类(WrapperClass)。包装类都位于java.lang包中。包装类与基本数据类型的对应关系如下表所示。八个类名中,除Integer类和Character类外,其余六个类的类名与基本数据类型一致。只需将类名的第一个字母大写即可。为什么需要包装类?很多人都有疑问。既然Java为了提高效率提供了八种基本数据类型,为什么还要提供包装类呢?这个问题,其实之前已经有人回答过了,因为Java是一门面向对象的语言,很多地方需要用到对象而不是基本数据类型。比如在集合类中,我们不能把int、double等类型放进去。因为集合的容器要求元素是Object类型。为了使基本类型也具有对象的特性,出现了包装类型,相当于对基本类型进行“包装”,使其具有对象的性质,并为其添加属性和方法,丰富了基本类型的操作。拆箱和装箱嗯,对于原始数据类型和包装类,有时必须在它们之间进行转换。例如,将基本数据类型的int转换为包装类型的Integer对象。我们认为包装类就是对基本类型的包装,所以把基本数据类型转换成包装类的过程就是包装。英文对应拳击,中文翻译为拳击。反之,将包装类转换为基本数据类型的过程就是拆包。英文对应unboxing,中文翻译为unboxing。在JavaSE5之前,给box,可以传入如下代码:Integeri=newInteger(10);自动拆箱和自动装箱在JavaSE5中,为了减少开发人员的工作量,Java提供了自动拆箱和自动装箱的功能。自动装箱:就是将基本数据类型自动转换成相应的包装类。自动拆箱:就是将包装类自动转换成对应的基本数据类型。Integeri=10;//自动装箱intb=i;//自动拆箱Integeri=10可以代替Integeri=newInteger(10);,这是因为Java为我们提供了自动装箱的功能,不需要开发者手动创建一个整数对象。自动装箱和自动拆箱的实现原理既然Java提供了自动拆箱的能力,那我们就来看看它的原理是什么,以及Java是如何实现自动拆箱功能的。自动拆箱我们有如下代码:publicstaticvoidmain(String[]args){Integerinteger=1;//boxinginti=integer;//unboxing}对上述代码进行反编译后,可以得到如下代码:publicstaticvoidmain(String[]args){Integerinteger=Integer.valueOf(1);inti=integer.intValue();}从上面的反编译代码可以看出,int的自动装箱是通过Integer.valueOf()方法实现的,Integer的自动拆箱是通过integer.intValue实现的。如果读者有兴趣,可以尝试反编译这八种类型,会发现如下规律:自动装箱是通过包装类的valueOf()方法实现的。自动拆箱是通过包装类对象xxxValue()来实现的。哪些地方会自动拆包拆箱?明白了原理之后,我们再来看看Java在什么情况下会自动帮我们解包拆箱。上面提到的变量初始化赋值的场景就不多介绍了,最简单也最容易理解。下面主要看看可能被忽略的场景。场景一、将基本数据类型放入集合类我们知道Java中的集合类只能接收对象类型,那么下面的代码为什么不报错呢?List
