包装类的意义
Java是一门面向对象的语言,但是Java的八种基本数据类型却没有对象的特征,更没有对象的功能(没有属性,不能调用方法)
基本数据类型不能调用方法,这就给我们很多的操作带来不便,另外容器(例如List、HashMap等)基本接收存储的都是
Object,不能接收基本数据类型。为了解决这个问题我们就要把所谓的基本数据类型包装成对象,使其具有对象的特征来方便使
用
class IntWrapper {
private int num ;
public IntWrapper(int num) {
this.num = num ;
}
public int intValue() {
return this.num ;
}
}
这里就写了一个int类型的包装类,如何使用?
public static void main(String[] args) {
Object obj = new IntWrapper(55) ; // 子类对象向上转型
IntWrapper temp = (IntWrapper) obj ; // 向下转型
System.out.println(temp.intValue()); // 取出里面的基本数据类型操作
//将基本数据类型包装为一个类对象的本质就是使用Object进行接收处理。
}
八种基本类型,如果都自己按照这样的操作包装的话,首先的问题代码的重复,其次就是在进行数学计算的时候,必须利
用明确的方法(如上面的intValue)将包装的数据取出后才可以进行运算。
所以Java为了方便开发使用,提供了包装类的支持
包装类
八种基本类型对应的包装类:
其中比较特殊的是int的包装类为Integer,char的包装类为character
这八个包装类可以根据他们的直接父类来分类:
对象型(Object的直接子类):Boolean、Character(char);
数值型(Number的直接子类): Byte、Double、Short、Long、Integer(int)、Float;
装箱与拆箱
在包装类与基本数据类型处理之中有装箱与拆箱的概念
装箱:将基本数据类型变为包装类对象,利用每一个包装类提供的构造方法实现装箱处理。
Integer num = new Integer(55) ; // 装箱
拆箱:将包装类中包装的基本数据类型取出。利用Number类中提供的六种方法。
boolean、char类型分别通过Boolean类中的booleanValue、Character类中的charValue方法拆箱
int data = num.intValue() ; // 拆箱
Number类
以上操作采用的是手工的装箱和拆箱。
在JDK1.5之后,提供了自动拆装箱的机制,最为重要的是由于此类机制的存在,可以直接利用包装类对象进行各种数学计算。
自动装箱与拆箱
// 自动装箱
Integer x = 55 ;
// 可以直接利用包装类对象操作
System.out.println(++x * 5 );
// 自动拆箱
int y = x ;
自动装箱拆箱到底是怎么实现的呢?(其他包装类相同)
自动装箱:调用Integer的valueOf()方法将原始类型值转换成对象
自动拆箱:调用Integer的intValue()方法,其他的(xxxValue())这类的方法将对象转换成原始类型值。
包装类与基本数据类型的比较
在Java中,说到比较应该立刻想到的就是“==”和equals
==
第一个ture是因为基本数据类型和包装类型(用==)比较时,会先把包装类拆箱再进行值比较
第二个false的原因是因为new了两个不同的对象,不同对象==比较的是地址,所以是false
这里咱们都是手动装箱的,我们把代码改一下用1.5之后提供的自动装箱来试试
我们换个值再试一试
这又是为什么呢?
因为之前说了,自动装箱利用的是valueOf()方法,答案我们可以在方法里一探究竟
感兴趣的朋友可以看看源码中的IntegerCache,我这里不再列举和详细说,直接说结论
对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区
间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个
大坑,所以说还是推荐使用 equals 方法进行判断。(这个缓存的上限127可以通过配置JVM更改)
除去Integer,其他包装类有没有缓存呢?
Byte,Short,Long类型有缓存(-128-127)
Character缓存0-127
Boolean缓存TRUE、FALSE
equals
之前说了推荐用equals方法进行比较,是因为包装类也将equals方法重写,利用equals方法比较,equals方法进行的是包
装类中的值比较(xxxValue() ),比较的是内容。而不是对象的地址。
使用基本数据类型还是包装类?
我们来看看阿里编码规约
关于基本数据类型与包装数据类型的使用标准如下:
1) 【强制】所有的 POJO 类属性必须使用包装数据类型。
2) 【强制】RPC 方法的返回值和参数必须使用包装数据类型。
3) 【推荐】所有的局部变量使用基本数据类型。