java中Integer包装类装箱的一个细节详解

 更新时间:2018年07月31日 09:02:00   作者:沉默哥  
Java中的Integer是int的包装类型,下面这篇文章主要给大家介绍了关于java中Integer包装类装箱的一个细节的相关资料,文中介绍的这个细节挺重要的,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起看看吧

前言

java有八个基本数据类型,每个都有对应的一个包装类,比如int对应的Integer。 Integer 是int的包装类型,数据类型是类,初值为null,从jdk1.5开始,java引入了自动拆装箱,可以直接进行形如Integer i = 20形式的赋值,编译器会自动将其转换为Integer i = Integer.valueOf(20)进行装箱,拆箱则是将int j = i的形式转换成了int j = i.intValue()

装箱有个细节,如果不注意很容易出错,来看一下:

Integer i = 20;
Integer j = Integer.valueOf(20);

System.out.println(i == j);

上面的代码输出为

true

好像没什么问题,那我们形式不变,将数字20换成200,即

i = 200;
j = Integer.valueOf(200);

System.out.println(i == j);

同样的判断,输出变成了:

false

这是为什么呢?

先明确一点,经过编译器编译后,Integer i = 20转换成了Integer i = Integer.valueOf(20) ,和Integer j = Integer.valueOf(20)的定义完全一样,那为什么将20换成了200后判断结果不一样了呢?

我们来看看Integer.valueOf(int i)方法的内部:

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

可以看出当i在某个区间内时,直接返回了缓存数组IntegerCache.cache中的一个值,超出区间才new一个新的Integer对象。到这里我们大概就可以得出结论:20在缓存范围内所以直接用了缓存,但是200超出了缓存区间所以new了新对象,和原来对象的地址当然不会相同,所以返回false

再来看看IntegerCache,这是一个Integer的私有静态内部类,定义如下:

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) {
    int i = parseInt(integerCacheHighPropValue);
    i = Math.max(i, 127);
    // Maximum array size is Integer.MAX_VALUE
    h = Math.min(i, Integer.MAX_VALUE - (-low));
   }
   high = h;

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

  private IntegerCache() {}
 }

可以看出默认的缓存区间是-128~127,那么什么情况下会修改这个范围呢,修改了某个虚拟机参数的时候,通过代码也可看出,设置的这个缓存上限java.lang.Integer.IntegerCache.high值不能小于127,小于的话就会被赋予127,从而失效。
那么这个值怎么设置呢?我们来看看jdk源码中怎么解释IntegerCache这个静态内部类:

Cache to support the object identity semantics of autoboxing for values between -128 and 127 (inclusive) as required by JLS. The cache is initialized on first usage. The size of the cache may be controlled by the -XX:AutoBoxCacheMax= option. During VM initialization, java.lang.Integer.IntegerCache.high property may be set and saved in the private system properties in the sun.misc.VM class.

大概意思是:

将-128到127(包含)的数字做缓存以供自动装箱使用。缓存在第一次使用时被初始化。大小可以由JVM参数-xx:autoboxcachemax=option来指定。JVM初始化时此值被设置成java.lang.Integer.IntegerCache.high属性并作为私有的系统属性保存在sun.misc.vm.class中。

可以得到结论:这个缓存的high值是由JVM参数 -XX:AutoBoxCacheMax= option来指定的。

上述jdk源码来源于jdk1.7,不同版本实现略有不同,但思路一致。

这种共享常用对象的思路有一个名字,叫享元模式,英文名叫Flyweight,即共享的轻量级元素。其他包装类如Boolean、Byte、Short、Long、Charactor都有类似的实现。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • 浅谈JSONObject的使用及示例代码(JSON解析)

    浅谈JSONObject的使用及示例代码(JSON解析)

    这篇文章主要介绍了浅谈JSONObject的使用及示例代码(JSON解析),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • java bootclasspath的具体用法

    java bootclasspath的具体用法

    本文主要介绍了java bootclasspath的具体用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • 用GUI实现java版贪吃蛇小游戏

    用GUI实现java版贪吃蛇小游戏

    这篇文章主要为大家详细介绍了用GUI实现java版贪吃蛇小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • Java项目防止SQL注入的几种方法总结

    Java项目防止SQL注入的几种方法总结

    SQL注入是比较常见的网络攻击方式之一,在客户端在向服务器发送请求的时候,sql命令通过表单提交或者url字符串拼接传递到后台持久层,最终达到欺骗服务器执行恶意的SQL命令,下面这篇文章主要给大家总结介绍了关于Java项目防止SQL注入的几种方法,需要的朋友可以参考下
    2023-04-04
  • java中关于getProperties方法的使用

    java中关于getProperties方法的使用

    这篇文章主要介绍了java中关于getProperties方法的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Redis中的事务和Redis乐观锁详解

    Redis中的事务和Redis乐观锁详解

    这篇文章主要介绍了Redis中的事务和Redis乐观锁详解,Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行,事务在执行的过程中,不会被其他客户端发送来的命令请求所打断,需要的朋友可以参考下
    2023-12-12
  • 详解SpringBoot Start组件开发之记录接口日志信息

    详解SpringBoot Start组件开发之记录接口日志信息

    这篇文章主要为大家介绍了SpringBoot-Start组件开发之记录接口日志信息详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 浅析Java中String与StringBuffer拼接的区别

    浅析Java中String与StringBuffer拼接的区别

    String拼接会创建一个新的String对象,存储拼接后的字符串,StringBuffer拼接是直接在本身拼接,会即时刷新。下面通过本文给大家介绍Java中String与StringBuffer拼接的区别,感兴趣的朋友一起看看吧
    2017-06-06
  • Java Web使用简单的批处理操作(记事本+Tomcat)

    Java Web使用简单的批处理操作(记事本+Tomcat)

    这篇文章主要介绍了Java Web使用简单的批处理操作 ,需要的朋友可以参考下
    2014-10-10
  • java输入多个数据(不确定),排序,并求最大值的方法

    java输入多个数据(不确定),排序,并求最大值的方法

    今天小编就为大家分享一篇java输入多个数据(不确定),排序,并求最大值的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07

最新评论