如何理解Java中的自动拆箱和自动装箱?

小伟刚毕业时面的第一家公司就被面试官给问住了...java

如何理解Java中的自动拆箱和自动装箱?web

自动拆箱?自动装箱?什么鬼,听都没听过啊,这...这..知识盲区...面试

回到家后小伟赶忙查资料,我透,这不就是问基本类型跟封装类型吗,面试官整啥名词呢...数据库

别问结果,问就是没过。数组

一、 什么是自动装箱,自动拆箱

定义:基本数据类型和包装类之间能够自动地相互转换缓存

理解:装箱就是自动将基本数据类型转换为封装类型,拆箱就是自动将封装类型转换为基本数据类型。编辑器

咱们知道,Java中提供了四大类基本数据类型,分别是:整数、浮点数、字符型和布尔型,其中:学习

  • 整数包含:byte、int、short、long
  • 浮点数包含:float、double
  • 字符类型:char
  • 布尔类型:boolean

基本数据类型相信你们必定很熟悉了吧,来来来,说说他们的取值范围~spa

数据类型 取值范围
byte -128 ~ 127
short -32786 ~ 32767
int -4294967296 ~ 4294967295
long -2^64^ ~ 2^64^ -1
float 3.4e-038 ~ 3.4e+038
double 1.7e-308 ~ 1.7e+308
char \u0000 ~ \uffff
boolean true 、false

平常开发中,靠这些基本数据类型几乎可以知足咱们的需求,可是基本类型终究不是对象,往重了说不知足面向对象的开发思想,往轻了说就是使用不方便。怎么讲?例如作一些数据类型转换,获取int数据类型的取值范围等等。设计

咱们知道,类的优势在于它能够定义成员变量、成员方法,提供丰富便利的功能,所以Java在JDK1.0的时候就设计了基本数据类型的包装类,而在JDK1.5中引入了新特性:自动装箱和拆箱。

咱们来看一下基本类型跟封装类型之间的对应关系:

数据类型 封装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

二、 使用包装类型后的便捷

咱们以上边提到的数据类型转换为例,看看使用包装类型后的便捷性。

小伟在数据库中存放商品库存用的是 varchar 类型来存储的,因此在代码中的实体与之对应的是 String,那么问题来了,既然是库存,那么势必就要用到加减乘除之类的运算,因此就须要先转换成 数值类型(int\long\float等)来运算,咱们看一下经过包装类是如何快速转换的「int\long\float」:

public class Test {
    public static void main(String[] args) {
        // 数据库中的商品数量 number
        String number = "666";
        // 借助封装了 Integer 转换为 int
        int intVal = Integer.valueOf(number);
        // 借助封装了 Float 转换为 float
        float floatVal = Float.valueOf(number);
        // 借助封装了 Long 转换为 long
        long longVal = Long.valueOf(number);
        // 依次输出三个值的内容
        System.out.println("int="+intVal);
        System.out.println("floatVal="+floatVal);
        System.out.println("longVal="+longVal);
    }
}

三、 落实自动装箱、拆箱

看完了包装类型的便捷性后,咱们再来落实到自动装箱、自动拆箱上...

怎么就自动装箱,自动拆箱了呢?

上一段代码,看看哪是自动装箱跟自动拆箱:

// 自动装箱
1. Integer a = 100;
// 自动拆箱
2. int b = a;

自动装箱,至关于Java编译器替咱们执行了 Integer.valueOf(XXX);

自动拆箱,至关于Java编译器替咱们执行了Integer.intValue(XXX);

咱们证明一下,首先经过 javac 编译获得 class 文件,接着反编译看看:

指令为:javap -c class文件名,获得下图所示:

看完编译器替咱们作的,接下来咱们再经过源码看看,首先是自动装箱 valueOf() 方法:

public static Integer valueOf(int i) {
 if (i >= IntegerCache.low && i <= IntegerCache.high)
  return IntegerCache.cache[i + (-IntegerCache.low)];
 return new Integer(i);
}

咱们能够看到,首先是if方法, 对传入的int 数值进行判断,若是 i >= -128i <= 127 那么就会从IntegerCache缓存中获取指定数字的封装类,若是不存在则 new 出一个新的封装类,关于 IntegerCache ,其内部实现了一个Integer的静态常量数组,在类加载的时候,执行static静态块进行初始化-128~127之间的Integer对象,存放到cache数组中,cache属于常量,存放在java的方法区中,对方法区不太了解的小伙伴能够先留空,后面我会单独水一篇的~

额外补充一下:上边咱们只看了Integer封装类的自动装箱方法,从方法中咱们了解了在-128~127之间使用了缓存,那么是否是意味着别的封装类也是这样呢?其实不是的,首先Integer使用缓存缘由是该区间会被常用到,且数量个数比较肯定,就256个值,因此为了提升效率,防止每次自动装箱都建立一次对象实例,而后就你懂得~,而double、float浮点型是没有使用缓存的,由于小数点的缘由,因此在这个区间范围内个数是比较泛的,即不适合缓存,没有意义。

咱们经过一段代码看看这个缓存的效果吧:

public class Test2 {
    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        Integer c = 200;
        Integer d = 200;
        System.out.println(a==b); // 打印true
        System.out.println(a==b); // 打印false
    }
}

接着再来看自动拆箱 intValue() 方法:

private final int value;

public int intValue() {
 return value;
}

这个方法就比较简单了,调用时直接返回了基本数据类型的 value 值。

至此咱们看完了自动装箱、自动拆箱,以Integer为例咱们知道了使用 valueOf() 方法实现装箱,使用 intValue() 方法实现拆箱,接下来咱们再结合几行代码从新回顾一下:

1. Integer a = new Integer(100);
2. Integer b = 100;
3. b+=100;
  • 第一行代码:new 了一个 Integer 对象实例,将 int 类型的数据传入包装成了 Integer 类型。

  • 第二行代码:首先咱们知道 100 是 int 类型的,可是等待复制的 b 是 Integer 类型,此时就用到了自动装箱,b = Integer.valueOf(100),将100包装成包装类了「经过反编译验证」

  • 第三行代码:用到了自动装箱+自动拆箱,b = b + 100 = Integer.intValye(b) + 100 此时计算结果获得的应该是 int 类型的 b,可是 b 又被限定了是 Integer 类型,因此就又要用到 Integet.valueOf() 自动装箱。

四、 上才艺

才艺一:如何理解Java中的自动拆箱和自动装箱?

答:自动装箱就是将基本数据类型自动转换为封装类型,自动拆箱是将封装类型自动转换为基本数据类型。

才艺二:能说一下是经过哪些方法实现自动拆箱、装箱的吗?

答:以Integer为例,使用Integer.valueOf()方法实现装箱,使用Integer.intValue()方法实现拆箱。

推荐阅读:

跟小伟一块儿学习类加载机制

为何有这么多领优惠劵的群?

单招计算机类哪一个专业比较好

相关文章
相关标签/搜索