自动装箱和拆箱
自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的互相转化。JDK1.5以后Java引入了自动装箱(autoboxing)和自动拆箱(unboxing)
自动装箱:
基本数据类型处于需要对象的环境中时,会自动转为”对象“。例如:‘
Integer i= 5;相当于编译器自动执行Integer i= Integer,valueOf(5)
自动拆箱子:
每当需要一个值时,对象会自动转成基本数据类型,没必要再去使用intvalue()
自动装箱过程时通过包装类的valueOf()方法,而自动拆箱过程是通过调用包装类的xxxValue()方法实现的(xxx代表的时对应的基本数据类型,如intVlaue(),doubleValue()等
自动装箱拆箱实际上是编译器来帮的忙,编译器在编译时依据你所写的语法,来决定是否进行装箱或者拆箱动作。
/*
* 自动装箱/自动拆箱
*/
package com.wu.test;
public class AutoboxingUnboxing {
public static void main(String[] args) {
Integer i = 100;//自动装箱
// 相当于编译器自动为你做一下语法编译:
// Integer i = Integer.valueOf(100);调用的是valueOf(100),而不是new Integer(100);
int j = i;//自动拆箱
// 相当于编译器自动为你做一下语法编译:
// int j = i.intValue();
}
}
所以自动装箱和自动拆箱的功能是所谓的“编译器蜜糖(Complier Suger)”虽然使用这个功能很方便,但是在程序运行阶段得了解java的语义。
包装类空指针异常问题:
/*
* 测试包装类空指针异常
*/
package com.wu.test;
public class Test01 {
public static void main(String[] args) {
Integer i = null;
int j = i;
/*代码在编译时期是合法的,但是在运行时期会有错误
* 因为其相当于下面两行代码
* Integer i= null;
* int j = i.intvalue();
*/
}
}
Exception in thread "main" java.lang.NullPointerException
at com.wu.test.Test01.main(Test01.java:10)
null表示i没有指向任何对象的实体,但作为对象的名称是合法的(不管这个对象名称是否指向某个对象的实体),由于实际上i 并没有指向任何对象的实体,所以也就不可能操作intValue()方法,这样上面的写法会出现NullPointerException的错误
自动装箱与拆箱:
/*
* 自动装箱与拆箱
* 结论:虽然很方便,但是不熟悉特性可能会出错。
*/
package com.wu.test;
public class Test02 {
public static void main(String[] args) {
Integer b = 23; //自动装箱
int a = new Integer(20);//自动拆箱
// 下面的问题我们需要注意》
Integer d = null ;
int c = d;//此处就是:d.intValue(),因此抛空指针异常。
}
}
包装类的缓存问题
整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存 处理,其目的是提高效率。
缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间 的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。
/*
* 包装类的缓存测试:
*/
package com.wu.test;
public class Test03 {
public static void main(String[] args) {
Integer in1 = -128;
Integer in2 = -128;
System.out.println(in1 == in2);//因为-128在缓存范围之内,当数字在[-128,127]之间时,返回的时数组中的某个元素
System.out.println(in1.equals(in2));//true,因为equals方法是数值的比较
Integer in3 = 1234;
Integer in4 = 1234;
System.out.println(in3 == in4);//因为1234不在缓存范围之内
System.out.println(in3.equals(in4));//true
}
}
注意:
1》JDK1,5以后,增加了自动装箱拆箱的功能,如:Integer i=100;int j = new Integer(100);
2》自动装箱调用的是valueOf()方法,而不是new Integer()方法。
3》自动拆箱调用的是xxxvalue()方法。
4》包装类为提高效率,对于-128~127范围类的值会进行缓存处理,超出范围后,对象之间不能再使用==进行数值比较,而是使用equals()方法。
/*
* 定义一个简单的包装类:
*/
public class MyInteger {
private int value;
private static MyInteger[] cache = new MyInteger[256];
public static final int Low = -128;
public static final int High = 127;
static {
//[-128,127]
for (int i=MyInteger.Low;i<=High;i++){
//-128,0;-127,1;-126,2;
cache[i+128] = new MyInteger(i);
}
}
public static MyInteger valueOf(int i){
if(i>=Low&&i<=High){
return cache[i+128];
}
return new MyInteger(i);
}
@Override
public String toString() {
return this.value+ "";
}
public int intValue(){
return value;
}
private MyInteger(int i){
this.value = i;
}
public static void main(String[]args){
MyInteger m = MyInteger.valueOf(30);
System.out.println(m);
}
}
1、
基本数据类型 |
包装类 |
int |
Integer |
byte |
Byte |
long |
Long |
short |
Short |
char |
Character |
double |
Double |
float |
Float |
boolean |
Boolean |
2、Number类和数字包装类是父子类关系,Number类是抽象类
3、包装类的两个基本作用:1.基本类型和包装类对象之间的互相转化2、包含每种基本数据类型的属性如:最大值,最小值等,以及相关操作等。
4、自动装箱拆箱指的是编译器在不同环境下根据书写语法对基本数据类型和包装类对象自动的调用Integer.valureOf()和xxxValue();方法转化
5、Integer类缓存的处理范围是【-128,127】。