Java Integer之IntegerCache

2024-01-02 17:59:11

????????前两天看了篇帖子,两个Integer对象做比较时,会产生意想不到的结果。想起之前也有遇到这样的情况,一直没有总结,今天简单记录一下。

相信大家一定遇到过这样的问题:==与equals有什么不同?

????????两者都需要区分基本数据类型与非基本数据类型。

????????对于==来说,如果是基本数据类型则比较值是否相等,如果是(非基本数据类型)对象则比较指向该对象的引用是否相等。

举个小例子:

Integer a = 100;
Integer b = 100;
System.out.println(a == b);// true

Integer c = 1000;
Integer d = 1000;
System.out.println(c == d);// false

然而

int e = 1000;
int f = 1000;
System.out.println(e == f);// true

那么为什么呢?

????????Java的8中基本类型分别是:byte、short、int、long、float、double、char和boolean。

????????Integer作为int类型的包装类型,并不属于Java中的8种基本类型。在Java中,除了上面的这8种类型,其他的类型都是对象,保存的是引用,而非数据本身。

????????至于为什么两次比较的结果不一致,暂且别急,先看看下面的问题:

Integer a = 1000;

Integer a = new Integer(1000);

// 这两者的区别在哪里?

????????对于前者来说,当你将一个基本类型值直接赋给一个包装类型的变量时,编译器会自动进行装箱操作,将基本类型值包装成对应的包装类型对象。

????????而后者这种方式使用了显式的构造函数调用。在这种情况下,通过使用构造函数new Integer(1000)来创建一个新的Integer对象。这种方式会在堆内存中为每个新创建的对象分配不同的内存空间,即使两个Integer对象的值相同。

? ? ? ? 要注意的是,前者写法并不是后者的简写形式。对后者来说其正确的简写形式为:

Integer a = Integer.valueOf(1000);

????????在定义对象a和b时,Java自动调用了Integer.valueOf来将数字封装成对象。

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

如果数字在low和high之间的话,是直接从IntegerCache缓存中获取的数据。

// IntegerCache源码:
private static class IntegerCache {
	static final int low = -128;
	static final int high;
	static final Integer[] cache;
	static Integer[] archivedCache;

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

            // Load IntegerCache.archivedCache from archive, if possible
            CDS.initializeFromArchive(IntegerCache.class);
            int size = (high - low) + 1;

        // Use the archived cache if it exists and is large enough
        if (archivedCache == null || size > archivedCache.length) {
            Integer[] c = new Integer[size];
            int j = low;
            for(int i = 0; i < c.length; i++) {
                c[i] = new Integer(j++);
            }
            archivedCache = c;
        }
        cache = archivedCache;
        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
	}
    private IntegerCache() {}
}

????????也就是说,如果数字在-128~127,是直接从 缓存 中获取的Integer对象。如果数字超过了这个范围,则是new出来的新对象。

????????文章中的1000,超出了-128~127的范围,所以对象a和b的引用指向了两个不同的地址;而100在-128~127的范围内,对象a和b的引用指向了同一个地址。

为什么Integer类会加这个缓存呢?

????????因为-128~127是使用最频繁的数字,如果不做缓存,会在内存中产生大量指向相同数据的对象,会浪费部分内存空间。

1234

文章来源:https://blog.csdn.net/m0_56426418/article/details/135339733
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。