zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    【LeetCode】在排序数组中查找元素的第一个和最后一个位置
    【LeetCode】搜索旋转排序数组
    【LeetCode】组合总和
    【LeetCode】电话号码的字母组合
    【LeetCode】对称二叉树
    【LeetCode】验证二叉搜索树
    【LeetCode】分发糖果
    Go学习笔记
    mybatis
    redis
  • 原文地址:https://www.cnblogs.com/shileibrave/p/9890903.html
Copyright © 2011-2022 走看看