• equals和==方法比较(三)--Long中LongCache源码分析


    下面我们来分析,上篇博客中遗留的问题,为什么下方的两个一个是true,两一个是false那?

    //true
    Long l1=123l;
    Long l2=123l;
    System.out.println(l1==l2);
    //false
    Long l1=123456l;
    Long l2=123456l;
    System.out.println(l1==l2);

    在上面的代码中,是把字面量赋值给了一个引用类型,在一般情况下这是不被允许的,但java中有自动装箱/自动拆箱的概念,导致了上面的赋值操作正常运行,也就是对于8种基本数据类型,都有对应的包装类,byte、short、int、long、float、double、char、boolean对应的包装类分别是Bytes、Short、Integer、Long、Float、Double、Character、Boolean。在Long l1=123l这行代码中就发生了自动装箱,即l1这个变量是引用类型的,其值为字面量。也就是l1、l2、l3、l4都为对象,那么使用==比较符比较的时候比较的肯定是内存地址,为什么一个true,一个false那。因为缓存,在Long类中存在LongCache缓存类,其源码如下,

    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静态内部类中,存在一个容量为256的Long类型的静态数组,其值的范围为-128~127。自动装箱的过程就像Long中的valueOf方法的过程如下,valueOf源码如下,

    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类型的对象,那么返回的是LongCache类中cache数组中的元素,而cache数组在类加载的时候已经初始化完毕(缓存),所以只要是在-128~127间的数据,不论多少个对象,返回的都是同一个对象,对同一个对象使用==比较符比较的时候肯定返回的是true,对于不在-128~127间的数就不是这个样子了。

    这样就解释了开头中一个为true,一个为falsle的原因。

    对于其他的包装类:Integer、Short、Character、Bytes等内部也有缓存类,但Integer缓存类中有high属性,可以设置缓存的最大范围(最小为-128)。

    参考:java中整型的缓存机制

    感谢,有问题欢迎指正!

  • 相关阅读:
    datagrid
    SQL语句
    JavaScript事件
    DOM和BOM
    JavaScript基础知识
    css
    网络编程常识
    集合框架
    多线程常识
    面向对象常识
  • 原文地址:https://www.cnblogs.com/teach/p/10251803.html
Copyright © 2020-2023  润新知