一. 自动装箱和拆箱的概念
自动装箱和拆箱主要指的java基本类型和对应的包装类之间的隐式转换。自动装箱就是将基本数据类型自动转化成对应的包装类,拆箱是把包装类自动转换成对应基本数据类型。java基本类型和对应的包装类如下:
二.自动装箱和拆箱的实现
- 代码示例
public class PrimitiveTypeWrapperTest {
public static void main(String[] args) {
//自动装箱
Integer i=6;
//自动拆箱
int a=i;
System.out.println("i:"+i);
System.out.println("a:"+a);
}
}
- 反编译class文件解析分析
L0
LINENUMBER 14 L0
BIPUSH 6
INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;
ASTORE 1
L1
LINENUMBER 16 L1
ALOAD 1
INVOKEVIRTUAL java/lang/Integer.intValue()I
ISTORE 2
在装箱的过程中,实际上是调用Integer包装类的valueOf()静态方法,而在装箱的过程中,实际上是调用Integer包装类intVaue()方法。
- Integer包装类valuesOf()和intValue()源码解析
public static Integer valueOf(int i) {
//1.判断int值是否在缓存里,如果存在从缓存取出,否则创建一个新的Integer对象
//2.IntegerCache存储的值范围在-128~127
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private final int value;
public int intValue() {
return value;
}
- Integer自动装箱题目示例
public class PrimitiveTypeWrapperTest {
public static void main(String[] args) {
Integer a=128;
Integer b=128;
Integer c=127;
Integer d=127;
System.out.println(a==b);//false
System.out.println(c==d);//true
}
}
==比较的是两个引用变量是否指向同一个对象,也就是指向对象的地址是否相同。a和b指向的对象在类初在加载的时候就已经初始化完毕,指向的是同一个对象。c和d因为不在缓存范围之内,每次都是重新初始化一个新的对象,在堆内存分配一个新的内存空间,指向的是新的对象,所以是false
思考:自动装箱除了Integer这样实现之外,其他包装类是否都是这样实现?
- 题目分析
public class PrimitiveTypeWrapperTest {
public static void main(String[] args) {
Float a=127.0f;
Float b=127.0f;
Double c=127.0;
Double d=127.0;
System.out.println(a==b);//false
System.out.println(c==d);//false
}
}
- Double和Float包装类valuesOf源码分析
//Double和Float做类型转换的时候都是直接初始化一个新对象
public static Double valueOf(double d) {
return new Double(d);
}
public static Float valueOf(float f) {
return new Float(f);
}
思考:Integer i=1;i+=1;做了什么事情?
- Integer i=1 自动装箱,调用valueOf方法
- i+1对象和基本类型运算,调用intValue方法将i转换成ini类型,运算结果是int类型
- 将i+1运算结果调用valueOf方法转换成Integer类型
思考:关于包装类equals()方法分析
- 代码示例
public class PrimitiveTypeWrapperTest {
public static void main(String[] args) {
Integer a=128;
Integer b=128;
System.out.println(a==b);//false
System.out.println(a.equals(b));//true
}
}
- equals()方法源码分析
//Object对象equals方法,比较的是否是同一个对象
public boolean equals(Ob,ject obj) {
return (this == obj);
}
//Integer包装类重写了equals方法,比较的是对象的值
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
对于所有的包装类都重写了equals方法,比较的都是对象的值