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

作者:沉默哥 时间:2023-09-24 18:35:32 

前言

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都有类似的实现。

来源:https://www.cnblogs.com/JackPn/p/9392145.html

标签:java,integer,包装类
0
投稿

猜你喜欢

  • java高并发的并发级别详解

    2023-08-05 15:44:38
  • springboot配置https访问的方法

    2022-12-11 16:17:37
  • 详解java中的阻塞队列

    2021-11-26 12:24:44
  • Springboot如何操作redis数据

    2022-05-30 21:36:41
  • Android 基于agora 开发视频会议的代码

    2021-11-30 02:53:04
  • Android Handle原理(Looper,Handler和Message)三者关系案例详解

    2023-08-25 22:51:47
  • java与scala数组及集合的基本操作对比

    2022-03-03 05:52:27
  • Spring Boot2.0中SpringWebContext找不到无法使用的解决方法

    2023-05-26 02:37:01
  • Android中bindService基本使用方法概述

    2023-08-05 19:18:56
  • 解决Android Studio突然不显示logcat日志的问题

    2021-06-09 01:13:13
  • Java面向对象编程的三大特征

    2023-09-19 06:20:34
  • 利用json2POJO with Lombok 插件自动生成java类的操作

    2023-07-12 09:31:28
  • Android中Fragment的基本用法示例总结

    2021-11-25 19:00:23
  • JAVA中阻止类的继承(官方和非官方)

    2023-06-29 16:02:56
  • android RecyclerView实现条目Item拖拽排序与滑动删除

    2023-03-20 20:50:36
  • Spring深入刨析声明式事务注解的源码

    2023-10-23 09:41:48
  • QT实现QML侧边导航栏的最简方法

    2021-09-17 02:54:35
  • thymeleaf中前后端数据交互方法汇总

    2023-07-18 21:15:59
  • C#通过NPOI操作Excel的实例代码

    2022-01-20 17:26:29
  • C#动态加载dll扩展系统功能的方法

    2022-08-08 23:23:15
  • asp之家 软件编程 m.aspxhome.com