java中的数据类型int,double等不是对象,未能通过向下变革获取到Object提供的方式,而像String却可以,只由于String是一个对象而不是一个类型。基本数据类型因为这样的特点,造成难以参与变革,子类,反射等过程。为了填补这个缺陷,java提供了包装类。
包装类顾名思义就是将基本的数据类型以及一些辅助方式包装到类中,比如自己实现一个int的包装类:
#5:f:e:0:e:8:0:8:b:b:2:3:c:9:3:8:b:3:6:4:f:8:9:f:e:5:6:2:8:6:6:6#
1.Java提供的包装类
其实里面的IntDemo类能实现一些辅助功能,并且可以支持子类反射等功能,而且假如假如每次使用都自己封装如此一个类的话,就太冗长了。所以,java为我们提供了基本数据类型的包装类,这种包装类分为两类,一种是对象型包装类,不承继任何其他类(Object的直接泛型),另一种是数值型包装类,承继于Number类。
对象型(Object的直接泛型)包装类:
#4:6:2:9:1:7:2:a:1:1:4:0:5:8:7:6:b:0:3:4:3:9:b:3:d:7:f:7:0:7:a:2#
数值型(承继了Number类)包装类:
#b:2:8:3:5:d:5:8:a:3:b:b:c:a:6:4:7:f:0:c:a:1:5:f:e:3:6:2:7:2:6:6#
Boolean和Character两个类就是正常的属性方式封装,而且数值型的包装类承继了一个Number类。
#3:d:f:c:7:c:e:6:7:0:4:e:0:9:c:d:d:6:a:b:2:4:3:c:0:1:0:7:a:5:9:4#
其中定义的方式如下:
#9:8:7:9:d:6:9:1:8:4:9:8:2:b:f:a:6:a:d:e:e:9:3:3:2:9:c:5:6:f:6:3#
虽然Number中定义的方式就是用于拆箱装箱的。
2.拆箱与装箱
装箱:
将基本数据类型封装为包装类对象,借助每一个包装类提供的构造方式实现装箱操作。
拆箱:
将包装类中包装的基本数据类型数据取出。
#f:5:c:5:7:3:f:e:5:d:6:b:a:b:7:3:8:5:c:d:0:0:6:3:5:b:b:6:3:2:8:1#
JDK1.5以后提供手动拆装箱。
#0:1:2:0:0:4:4:6:e:c:9:d:e:7:6:0:6:1:c:8:2:a:b:c:8:d:2:f:c:e:f:4#
3.手动装箱的显存复用
手动装箱时,对于Integervar=?,假如var指向的对象在-128至127范围内的形参时,生成的Integer实例化对象是由IntegerCache.cache()方式形成,它会复用已有对象。和String的共享池操作是一个道理,cache()方式会将坐落-128~127范围内形成的Integer对象入池,上次使用的时侯,从池中拿去,就不会在创建了。
所以,在这个数值区间内的Integer对象的栈指向(属性名)可以直接使用==进行判别,由于值相同,指向的就是同一片区域。并且这个区间之外的所有数据,手动装箱还会在堆上形成实例化,并不再复用已有对象,这是一个深坑,为了防止这个问题,推荐使用equals方式进行Integer的判别。
对于所有数值型的包装类来说,就会涉及到前面这些问题,一定要多加注意。
而对于自动装箱,即采用new进行包装类创建时,不会发生显存复用,由于new关键字每次使用,就会开辟新的空间,这和String采用构造方式创建字符串不入池相对应。
4.包装类编码规约
所有的相同类型的包装类对象之间值的比较,全部使用equals()技巧。
所有的POJO(简单Java类,只包含基本属性,有参构造,get/set)类属性必须使用包装类数据类型,类属性即static属性。
RPC(远程方式调用)方式返回值和参数必须使用包装数据类型。
推荐所有的局部变量使用基本数据类型。
5.包装类对字符串与基本数据类型转换的支持
实际工程中,各类数据的接收是一般是通过字符串完成的,所以要把握包装类对字符串转换的技巧。
#b:f:1:f:0:6:c:2:0:7:1:9:b:6:9:f:0:2:6:e:c:c:c:2:d:b:b:d:5:1:f:8#
字符串转数值类型时字符串只能包含数字,否则会抛出NumberFormatException异常,这是一个非受查异常。
而且字符串转Boolean是个特例,parseBoolean()方式会将”true”转为true,而将非”true”的字符串转为false。