关于Java中Integer对象缓存问题的分析

这篇博客探讨了Java中Integer对象的缓存机制。通过反汇编class文件,展示了Integer.valueOf()方法如何根据传入值在-128到127之间时复用缓存对象,而超出范围则新建对象。博主还详细分析了IntegerCache内部类的实现,指出Integer缓存的下限固定为-128,上限默认为127但可配置,且在类初始化时填充缓存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AndroidSurface看的有点头晕,换个口味,下一篇再更

偶然网上看到如下代码:

public class IntegerTest {
    private Integer a = 100;
    private Integer b = 100;
    private Integer c = 200;
    private Integer d = 200;
    public static void main(String[] args) {
        new IntegerTest().test();
    }
    public void test(){
        System.out.println(a==b);
        System.out.println(c==d);
    }
}

输出结果如下:

true  // 表明 a 和 b 是同一个对象
false // 表明 c 和 d 不是同一个对象

大家可能已经知道这是关于Java整数对象缓存(-128–127)的问题。

我们看下到底为什么会这样

反汇编class文件

通过javap -c命令将class文件进行反汇编,内容如下:

public class hua.lee.test.IntegerTest {
  // 此处是编译后生成的对象初始化方法
  public hua.lee.test.IntegerTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: bipush        100
       7: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      10: putfield      #3                  // Field a:Ljava/lang/Integer;
      13: aload_0
      14: bipush        100
      16: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      19: putfield      #4                  // Field b:Ljava/lang/Integer;
      22: aload_0
      23: sipush        200
      26: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      29: putfield      #5                  // Field c:Ljava/lang/Integer;
      32: aload_0
      33: sipush        200
      36: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      39: putfield      #6                  // Field d:Ljava/lang/Integer;
      42: return

    ... // 省略部分
}

以变量a为例,它的核心赋值部分是:

       4: aload_0
       5: bipush        100
       7: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      10: putfield      #3                  // Field a:Ljava/lang/Integer;

invokestatic是执行一个静态方法的指令,这里执行的是Integer.valueOf(),也就是说

Java的自动装箱其实就是编译器编译时将Integer a = 100;转换为Integer a = Integer.valueOf(100);的操作

Integer.valueOf()

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.lowIntegerCache.high之间的话,会返回IntegerCache.cache数组中的Integer对象
  • 否则,new Integer()

IntegerCacheInteger的内部类,代码如下:

    private static class IntegerCache {
        // low 是写死的
        static final int low = -128;
        // 关于high,看样子是可以动态调整
        static final int high;
        // 用来缓存 Integer 对象的集合
        static final Integer cache[];
        static {
            // high value may be configured by property
            int h = 127;
            // 从 java.lang.Integer.IntegerCache.high 属性中读取缓存的上限
            String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            // 属性不为空,进行数值转换处理
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    // 不能小于 127
                    i = Math.max(i, 127);
                    // 确定数组上限
                    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++);

            // assert 保证上限 >= 127 
            assert IntegerCache.high >= 127;
        }
        private IntegerCache() {}
    }

关于Integer的缓存问题我们就分析完了

  • Integer缓存的下限是固定的-128
  • Integer缓存的上限可以通过java.lang.Integer.IntegerCache.high设置,但是必须>=127
  • Integer在类初始化的时候就把缓存集合cahce创建好了,并且在类初始化时会将cahce集合填充完成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值