详解Java 自动装箱与自动拆箱

 更新时间:2020年09月09日 15:07:44   作者:山禾说  
这篇文章主要介绍了Java 自动装箱与自动拆箱的相关资料,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下

包装器

有些时候,我们需要把类似于int,double这样的基本数据类型转成对象,于是设计者就给每一个基本数据类型都配置了一个对应的类,这些类被称为包装器。

包装器整体来说分为四大种:

  1. Number,Number类派生出了Integer,Double,Long,Float,Short,Byte这六个小类分别代表了int,double,long,float,short,byte这六种基本数据类型。
  2. Character,对应的基本数据类型是char。
  3. Void,对应的是关键字void,这个类我们会经常在反射中看到,用于表示方法的返回值是void,这里不再赘述,后面反射章节详细讲解。
  4. Boolean,对应的是基本数据类型boolean。

要记住下面两点包装器的特性:

包装器是不可变的,一旦构造了包装器,就不允许更改包装在其中的值。

  1. 包装器是final定义的,不允许定义它的子类。

自动装箱和自动拆箱

ArrayList<Integer> list = new ArrayList<>();

list.add(3);

int x = list.get(0);

自动装箱

当我们添加int值 到一个集合元素全部是Integer的集合中去时候,这个过程发生了什么?

list.add(3);

//实际上面的代码会被编译器给自动的变成下面的这个代码
list.add(Integer.valueOf(3))

编译器在其中所作的这个事情就叫做自动装箱。

自动拆箱

当我们取出一个集合中的元素并将这个元素赋给一个int类型的值的时候,这其中又发生了什么呢?

int x = list.get(0);

//实际上面的代码会被编译器给自动的变成下面的这个代码
int x = list.get(0).intValue();

编译器这其中所作的这个事情就叫做自动拆箱

自动装箱和自动拆箱中的坑

Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 300;
Integer i4 = 300;

System.out.println(i1 == i2);
System.out.println(i3 == i4);

这是一道经典的面试题,打印出来的结果是:

true
false

为什么会发生这样的事情,我们记得自动装箱的时候会自动调用Integer的valueOf方法,我们现在来看一下这个方法的源码:

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

而这个IntegerCache是什么呢?

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
      // high value may be configured by property
      int h = 127;
      String integerCacheHighPropValue =
        sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
      if (integerCacheHighPropValue != null) {
        try {
          int i = parseInt(integerCacheHighPropValue);
          i = Math.max(i, 127);
          // Maximum array size is Integer.MAX_VALUE
          h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
        } catch( NumberFormatException nfe) {
          // If the property cannot be parsed into an int, ignore it.
        }
      }
      high = h;

      cache = new Integer[(high - low) + 1];
      int j = low;
      for(int k = 0; k < cache.length; k++)
        cache[k] = new Integer(j++);

      // range [-128, 127] must be interned (JLS7 5.1.7)
      assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。

上面的代码中i1和i2的数值为100,因此会直接从cache中取已经存在的对象,所以i1和i2指向的是同一个对象,而i3和i4则是分别指向不同的对象。

这样我们就不难理解为什么一个是false,一个是true了。

其他的包装器的valueOf方法也有不同的实现和不同的范围,具体的我们会在源码深度解析专栏来分析,敬请期待~

以上就是详解Java 自动装箱与自动拆箱的详细内容,更多关于Java 自动装箱与自动拆箱的资料请关注脚本之家其它相关文章!

相关文章

  • 关于@RequestLine的使用及配置

    关于@RequestLine的使用及配置

    这篇文章主要介绍了关于@RequestLine的使用及配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • IntelliJ IDEA2022.3 springboot 热部署含静态文件(最新推荐)

    IntelliJ IDEA2022.3 springboot 热部署含静态文件(最新推荐)

    这篇文章主要介绍了IntelliJ IDEA2022.3 springboot 热部署含静态文件,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • Mybatis-Plus实现SQL拦截器的示例

    Mybatis-Plus实现SQL拦截器的示例

    这篇文章主要介绍了Mybatis-Plus实现一个SQL拦截器,通过使用SQL拦截器,开发人员可以在执行SQL语句之前或之后对其进行修改或记录,从而更好地控制和优化数据库操作,对Mybatis-Plus SQL拦截器相关知识感兴趣的朋友一起看看吧
    2023-05-05
  • 一篇文章告诉你JAVA Mybatis框架的核心原理到底有多重要

    一篇文章告诉你JAVA Mybatis框架的核心原理到底有多重要

    yBatis的底层操作封装了JDBC的API,MyBatis的工作原理以及核心流程与JDBC的使用步骤一脉相承,MyBatis的核心对象(SqlSession,Executor)与JDBC的核心对象(Connection,Statement)相互对应
    2021-06-06
  • Java实现的不同图片居中剪裁生成同一尺寸缩略图功能示例

    Java实现的不同图片居中剪裁生成同一尺寸缩略图功能示例

    这篇文章主要介绍了Java实现的不同图片居中剪裁生成同一尺寸缩略图功能,涉及java针对图片的读取、属性修改等相关操作技巧,需要的朋友可以参考下
    2017-09-09
  • 详解log4j-over-slf4j与slf4j-log4j12共存stack overflow异常分析

    详解log4j-over-slf4j与slf4j-log4j12共存stack overflow异常分析

    这篇文章主要介绍了详解log4j-over-slf4j与slf4j-log4j12共存stack overflow异常分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • 解决springboot与springcloud版本兼容问题(附版本兼容表)

    解决springboot与springcloud版本兼容问题(附版本兼容表)

    在基于spring boot搭建spring cloud时,创建eureka后启动服务发生报错,本文给大家介绍了解决springboot与springcloud版本兼容问题的几种方案,需要的朋友可以参考下
    2024-02-02
  • SpringMVC请求流程源码解析

    SpringMVC请求流程源码解析

    这篇文章主要介绍了SpringMVC请求流程源码分析,包括springmvc使用,SpringMVC启动过程及SpringMVC请求过程,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • Java中FileWriter的用法及wirte()重载方法详解

    Java中FileWriter的用法及wirte()重载方法详解

    这篇文章主要介绍了Java中FileWriter的用法及wirte()重载方法详解,FileWriter是Java编程语言中的一个类,用于将字符写入文件,它提供了一种简单而方便的方式来创建、打开和写入文件,通过使用FileWriter,我们可以将字符数据写入文本文件,需要的朋友可以参考下
    2023-10-10
  • 深入了解Spring的Bean生命周期

    深入了解Spring的Bean生命周期

    这篇文章主要为大家介绍了Spring的Bean生命周期,文中的示例代码讲解详细,对我们学习或工作有一定的参考价值,感兴趣的可以学习一下
    2022-01-01

最新评论