包装类型自动拆箱装箱汇总
一、手动装箱
1.通过构造函数创建的都是手动装箱
Integer a = new Integer(97);
2.通过valueOf()函数创建
Integer a = Integer.valueOf(97);
二、自动装箱
1.通过直接赋值创建的都是手动装箱,因为字面量是基本类型,要赋值为引用类型只能自动装箱,底层调用的实际是**valueOf()**函数
Integer a = 97;
2.集合添加元素:集合只能存放引用类型
List a = new ArrayList();
a.add(97);//自动变换为a.add(Integer.valueOf(97));
三、自动拆箱
1.直接赋值,实际调用的是a.intValue()进行拆箱
Integer a = 97;
int b = a;
2.基本运算 + - * /
自增自减运算 ++ –
==运算(详见第四节)
首先需明确包装类型进行运算时需先进行拆箱才能进行运算,因为包装类型本身的值不可变,所以只能拆箱进行运算后再重新进行装箱,此时符号引用指向的是一个不同的地址。例:
Integer a = 100;
Integer b = 100;
Integer c = a + b;//运算过程中进行了自动拆箱,因为使用Integer进行接收,再进行了自动装箱
Integer a = 1;
a++;//在自增过程中进行了自动拆箱和装箱
3.自动拆箱导致的问题
因为在sssss()中的x2是一个局部变量改变的是指向的地址,而不是指向地址的值,所以test5()中x2仍然指向原来的地址,该处位置的值并未被改变,仍输出原来的值。
Java方法中的引用传递:传递的是变量的地址,调用的方法改变的是指向地址的值,所以实参指向的该处的值会随方法改变而改变,而包装类型值不能改变,只能改变形参引用地址,而实参引用地址没有改变。
四、equals()和==
- equals()比较的是对象的类型和值,只有类型和值都相同,才会返回true
- ==根据参与运算的数据类型来比较值或者引用地址
- 如果都是基本类型,则比较值
- 如果一个是基本类型,一个是引用类型,则引用类型会自动拆箱,比较值
- 如果都是引用类型,则比较地址
例1:如下
例2:
Integer a = 100;
Integer b = 100;
a == b //true
Integer a = 200;
Integer b = 200;
a == b //false
以上两个例子都是引用类型比较地址,但是结果为什么不同呢?
因为valueOf()函数对于-127~128区间内的数值装箱时会返回同一个对象,
而超出该范围的会创建新对象,源码如下:
private static final Integer[] SMALL_VALUES = new Integer[256];
public static Integer valueOf(int i) {
return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];
}
例3:
int a = 200;
Integer b = 200;
a == b //true 自动拆箱,比较值
总结:
- 直接赋值是自动装箱,构造函数赋值是手动装箱
- 直接赋值在[-128,127]区间内的指向同一个对象,否则指向不同对象
- 包装类型进行运算时需自动拆箱,包括 + - * / ++ – == 等,其中==比较包装类型和基本类型时需自动拆箱,都是包装类型时则比较地址
- equals比较的是对象的值和类型
- 除Integer外的数值类包装类型(Double,Long等)都不指向同一个对象,而Boolean则是都指向同一个对象。例
Double a = 1.0;
Double b = 1.0;
a == b;//false
Boolean a = true;
Boolean b = true;
a == b;//true