包装类型自动拆箱装箱汇总

一、手动装箱

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.自动拆箱导致的问题


自动拆装箱java有什么好处 包装类自动拆装箱_java


因为在sssss()中的x2是一个局部变量改变的是指向的地址,而不是指向地址的值,所以test5()中x2仍然指向原来的地址,该处位置的值并未被改变,仍输出原来的值。

Java方法中的引用传递:传递的是变量的地址,调用的方法改变的是指向地址的值,所以实参指向的该处的值会随方法改变而改变,而包装类型值不能改变,只能改变形参引用地址,而实参引用地址没有改变。

四、equals()和==

  1. equals()比较的是对象的类型和值,只有类型和值都相同,才会返回true
  2. ==根据参与运算的数据类型来比较值或者引用地址
  • 如果都是基本类型,则比较值
  • 如果一个是基本类型,一个是引用类型,则引用类型会自动拆箱,比较值
  • 如果都是引用类型,则比较地址

例1:如下

自动拆装箱java有什么好处 包装类自动拆装箱_自动拆装箱java有什么好处_02


例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 自动拆箱,比较值

总结:

  1. 直接赋值是自动装箱,构造函数赋值是手动装箱
  2. 直接赋值在[-128,127]区间内的指向同一个对象,否则指向不同对象
  3. 包装类型进行运算时需自动拆箱,包括 + - * / ++ – == 等,其中==比较包装类型和基本类型时需自动拆箱,都是包装类型时则比较地址
  4. equals比较的是对象的值和类型
  5. 除Integer外的数值类包装类型(Double,Long等)都不指向同一个对象,而Boolean则是都指向同一个对象。例
Double a = 1.0;
Double b = 1.0;
a == b;//false

Boolean a = true;
Boolean b = true;
a == b;//true