Java开发之路

文章32 |   阅读 2178 |   点赞0

来源:https://blog.csdn.net/sunnyyoona

[Java开发之路](19)Long缓存问题

x33g5p2x  于2021-03-13 发布在 其他  
字(1.1k)|赞(0)|评价(0)|浏览(85)

Long中有个小小的陷阱,就是在-128至127范围内,Long.valueOf(long l)返回的Long的实例是相同的,而在此范围之外每次使用valueOf(long l)时,返回的实例都是不同的。

举例:

System.out.println(Long.valueOf(-129) == Long.valueOf(-129)); // false
System.out.println(Long.valueOf(-128) == Long.valueOf(-128)); // true
System.out.println(Long.valueOf(127) == Long.valueOf(127)); // true
System.out.println(Long.valueOf(128) == Long.valueOf(128)); // false

下面我们通过Long源码进行分析一下:

    public static Long valueOf(long l) {
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
    }

从上面代码中我们可以看出先判断传递过来的数值是否在[-128,127]之间,如果是则直接从缓存中返回对应的引用,否则新创建一个Long的实例。所以说如果不在这个区间范围内,返回一个新创建的Long类型引用,用==判断就会理所当然的返回false,地址不一样。但是如果我们使用equals方法,则会返回true,数值是一样的。

Long.valueOf(128).equals(Long.valueOf(128))  // true

我们看看对于在区间范围之内,是如何返回对应的引用?最重要的是Long类中有一个静态的内部类LongCache,专门用于缓存-128至127之间的值。

    private static class LongCache {
        private LongCache(){}

        static final Long cache[] = new Long[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Long(i - 128);
        }
    }

在LongCache类中定义了一个cache数组,来存储缓存数据。我们可以看到cache数组的长度:-(-128) + 127 + 1,很明了的知道缓存数据从-128到127,后面的1代表数字0,一共256个元素。

valueOf这个方法设计比较好的一点是offset,它的初始值设为128,目的就是为了数组下标128处存放0,这样就将正数和负数分隔开。

相关文章