JDK1.8 Integer,Long等的缓存策略

 1 public class IntegerTest {
 2     public static void main(String[] args) {
 3         Integer a = 10;
 4         Integer b = 10;
 5         System.out.println(a==b);
 6 
 7         Integer c = 1000;
 8         Integer d = 1000;
 9         System.out.println(c==d);
10     }
11 }

上面这段代码输出:

true
false

纳尼?不都是引用比较吗?值相等,引用不相等,应该都返回false吧?别着急,我们下面分析一下。

原因:在 Java 5 中,为 Integer 的操作引入了一个新的特性,用来节省内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。对整数区间 -128 到 +127的整数都做了缓存,到Java 8开始缓存范围改为-128 到 N。其中N为可配置参数。

再看一段代码:

1 public class IntegerTest {
2     public static void main(String[] args) {
3         Integer a1 = new Integer(10);
4         Integer b1 = new Integer(10);
5         System.out.println(a1==b1);
6     }
7 }

这个输出结果是什么呢?估计你们已经猜到了,既然让我们猜肯定是false啊。不然还猜个屁!没错答案就是false。为什么呢?

原因:这种 Integer 缓存策略仅在自动装箱(autoboxing)的时候有用,使用构造器创建的 Integer 对象不能被缓存。

自动装箱,拆箱不懂?自己另行百度吧。

看下一下Integer缓存实现的源码IntegerCache类:

支持 -128 到 127 之间的自动装箱过程。最大值 127 可以通过 JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改。初始化的时候通过for循环将-128到AutoBoxCacheMax之间的数组装载到cache数组。

 1     /**
 2      * Cache to support the object identity semantics of autoboxing for values between
 3      * -128 and 127 (inclusive) as required by JLS.
 4      *
 5      * The cache is initialized on first usage.  The size of the cache
 6      * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
 7      * During VM initialization, java.lang.Integer.IntegerCache.high property
 8      * may be set and saved in the private system properties in the
 9      * sun.misc.VM class.
10      */
11 
12     private static class IntegerCache {
13         static final int low = -128;
14         static final int high;
15         static final Integer cache[];
16 
17         static {
18             // high value may be configured by property
19             int h = 127;
20             String integerCacheHighPropValue =
21                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
22             if (integerCacheHighPropValue != null) {
23                 try {
24                     int i = parseInt(integerCacheHighPropValue);
25                     i = Math.max(i, 127);
26                     // Maximum array size is Integer.MAX_VALUE
27                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
28                 } catch( NumberFormatException nfe) {
29                     // If the property cannot be parsed into an int, ignore it.
30                 }
31             }
32             high = h;
33 
34             cache = new Integer[(high - low) + 1];
35             int j = low;
36             for(int k = 0; k < cache.length; k++)
37                 cache[k] = new Integer(j++);
38 
39             // range [-128, 127] must be interned (JLS7 5.1.7)
40             assert IntegerCache.high >= 127;
41         }
42 
43         private IntegerCache() {}
44     }

再来看一下Integer的valueof()方法:

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

从上面的代码可以看到每次通过valueOf做装箱的时候,都会判断int i是否在-128到127之间。在的话直接从cache数组取出来返回。所以,

Integer a = 10;
Integer b = 10;

a和b返回的都是IntegerCache.cache[138]这个引用,最后做==比较的时候自然结果为true。

原文地址:https://www.cnblogs.com/shileibrave/p/9890903.html