我是靠谱客的博主 紧张凉面,最近开发中收集的这篇文章主要介绍java.lang.Integer包装类的缓存,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1. 发现问题

先看一段代码:

Integer a = 1;
Integer b = 1;
Integer c = 500;
Integer d = 500;
System.out.print(a == b);
System.out.print(c == d);

输出是啥?输出的结果如下:

true
false

为啥?两个不都是引用吗?要输出false应该都输出false啊?下面解释原因。

2. 分析问题

2.1 字节码分析

首先我们分析自动装箱,下面的这行代码会发生什么?

Integer a = 1;

我们用查看其编译后的字节码,看这行代码到底在干啥。

0 iconst_1 // 将int型1推送至栈顶
1 invokestatic #2 <java/lang/Integer.valueOf> // 调用Integer.valueOf方法
4 astore_1 // 将栈顶引用型数值存入第一个本地变量

显然,通过字节码我们知道上面的代码等价于如下代码:

Integer a = Integer.valueOf(1);

2.2 Integer#valueOf 方法源码分析

那么这也并不能说明文章开头的输出结果啊!那么我们再分析分析,猜测Integer.valueOf函数很可能有一些特殊的地方。

下面查看Integer.valueOf(int)

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

通过查看Integer的valueOf源码,发现,它并不是简单的new出一个Integer对象并返回,而是做了一个前置判断。通过判断代码,可以猜测这跟缓存(IntegerCache)有关,也就是IntegerCache这个类。

2.3 Integer.IntegerCache 类源码分析

那我们再看到IntegerCache这个类:Integer.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 {@code -XX:AutoBoxCacheMax=<size>} 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.
 */

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() {}
}

通过查看类的注解,我们知道Integer能够默认缓存[-128, 127]范围内的Integer对象。也就是说当我们调用Integer.valueOf(x),如果x是在[-128, 127]区间的数,那么它就能够直接返回已经创建在cache[]数组中创建过的Integer对象(这些缓存的Integer对象都存在IntegerCache类的cache[]字段中)

那么文章开头的那个输出结果也就解释得通了。

// 属于[-128, 127]区间,那么直接返回IntegerCache类cache[]已经缓存的Integer对象
Integer a = 1; 
// 同上
Integer b = 1;
// 并不属于[-128, 127]区间,直接返回new Integer(500);
Integer c = 500;
// 同上,这两个返回的引用并不一样
Integer d = 500;

3. 更多

通过注释,我们也知道了:通过-XX:AutoBoxCacheMax=<size>可以调整这个缓存区间的上界。

下面我们实践一下:

public class Test {

    public static void cmp(Integer i1, Integer i2){
        System.out.println(i1 == i2);
    }

    public static void main(String[] args) {


        Integer i1 = -128;
        Integer i2 = -128;

        cmp(i1, i2);

        Integer i3 = 127;
        Integer i4 = 127;

        cmp(i3, i4);

        Integer i5 = -129;
        Integer i6 = -129;

        cmp(i5, i6);

        Integer i7 = 128;
        Integer i8 = 128;
        cmp(i7, i8);
    }
}

首先我们在命令行下运行下面的代码:

>javac Test.java
>java Test
true
true
false
false

我们可以看到这正如我们预期的结果一样。那么我们再试试下面的代码:

>java -XX:AutoBoxCacheMax=129 Test
true
true
false
true

看到,最后一项输出为true,验证了参数-XX:AutoBoxCacheMax=129的正确性

4. 拓展

同样地,分析各种基本数据类型的包装类,它们的valueOf方法有下面的缓存区间

  • boolean{true, false}
  • byte缓存所有
  • short[-128, 127]
  • long,[-128, 127]
  • char['u0000', 'u007F']
  • float,double直接new一个新的对象,并没有缓存
    而这些数据类型的valueOf与Integer的又不一样,它们的缓存是固定的,而Integer的缓存是可以通过上面所描述的方法来更改的

最后

以上就是紧张凉面为你收集整理的java.lang.Integer包装类的缓存的全部内容,希望文章能够帮你解决java.lang.Integer包装类的缓存所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部