下面我们来分析,上篇博客中遗留的问题,为什么下方的两个一个是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中整型的缓存机制

感谢,有问题欢迎指正!

equals和==方法比较(三)--Long中LongCache源码分析的更多相关文章

  1. 【原】Spark中Client源码分析(二)

    继续前一篇的内容.前一篇内容为: Spark中Client源码分析(一)http://www.cnblogs.com/yourarebest/p/5313006.html DriverClient中的 ...

  2. 【原】Spark中Master源码分析(二)

    继续上一篇的内容.上一篇的内容为: Spark中Master源码分析(一) http://www.cnblogs.com/yourarebest/p/5312965.html 4.receive方法, ...

  3. 【原】 Spark中Worker源码分析(二)

    继续前一篇的内容.前一篇内容为: Spark中Worker源码分析(一)http://www.cnblogs.com/yourarebest/p/5300202.html 4.receive方法, r ...

  4. php中foreach源码分析(编译原理)

    php中foreach源码分析(编译原理) 一.总结 编译原理(lex and yacc)的知识 二.php中foreach源码分析 foreach是PHP中很常用的一个用作数组循环的控制语句.因为它 ...

  5. 手把手教你实现栈以及C#中Stack源码分析

    定义 栈又名堆栈,是一种操作受限的线性表,仅能在表尾进行插入和删除操作. 它的特点是先进后出,就好比我们往桶里面放盘子,放的时候都是从下往上一个一个放(入栈),取的时候只能从上往下一个一个取(出栈), ...

  6. Java中ArrayList源码分析

    一.简介 ArrayList是一个数组队列,相当于动态数组.每个ArrayList实例都有自己的容量,该容量至少和所存储数据的个数一样大小,在每次添加数据时,它会使用ensureCapacity()保 ...

  7. Java中HashMap源码分析

    一.HashMap概述 HashMap基于哈希表的Map接口的实现.此实现提供所有可选的映射操作,并允许使用null值和null键.(除了不同步和允许使用null之外,HashMap类与Hashtab ...

  8. 动态代理以及对应Spring中AOP源码分析

    AOP(面向切面编程)在Spring中是被广泛应用的(例如日志,事务,权限等),而它的基本原理便是动态代理. 我们知道动态代理有两种:基于JDK的动态代理以及基于CGlib动态代理.以下是两种动态代理 ...

  9. [dpdk] 熟悉SDK与初步使用 (三)(IP Fragmentation源码分析)

    对例子IP Fragmentation的熟悉,使用,以及源码分析. 功能: 该例子的功能有二: 一: 将IP分片? 二: 根据路由表,做包转发. 路由表如下: IP_FRAG: Socket : ad ...

随机推荐

  1. 查找系统中jdk的位置

    查找系统中jdk的位置: [root@localhost native]# find /|grep jni_md.h /var/lib/docker/overlay2/ec7a5439382a8a6d ...

  2. JDK(五)JDK1.8源码分析【集合】HashMap

    本文转载自无始无终,原文连接 HashMap 在 JDK 1.8 后新增的红黑树结构 传统 HashMap 的缺点 JDK 1.8 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也 ...

  3. 【noip 模拟赛curse,light,maze】 题解

    2018.10.16 总结:考的不好 原因: 1.考的时候没状态,读题读不进去 2.考的时候不仔细,该得分没得到 T1:curse 1.咒语 (curse.pas/c/cpp) [题目描述] 亮亮梦到 ...

  4. Jfinal框架登陆页面的图形验证码

    本文转自,http://www.bubuko.com/infodetail-720511.html 验证码的工具类, 这个jfinal自带的也有,但是下面这个和Jfinal自带的有一点点小的改动,(我 ...

  5. linux 进程间通信方式

    管道: 它包括无名管道和有名管道两种,前者用于父进程和子进程间的通信,后者用于运行于同一台机器上的任意两个进程间的通信消息队列: 用于运行于同一台机器上的进程间通信,它和管道很相似,是一个在系统内核中 ...

  6. 轻量ORM-SqlRepoEx (十六)最佳实践之Dapper(2)

    简介:SqlRepoEx是 .Net平台下兼容.NET Standard 2.0人一个轻型的ORM.解决了Lambda转Sql语句这一难题,SqlRepoEx使用的是Lambda表达式,所以,对c#程 ...

  7. 一个loser的忏悔

    一直认为自己是世界的主角,从小意气用事,耽误了学业,现在才发现了自己的爱好,于是开始努力进阶. 愿不辜负自己的努力! 高中大学青葱旺盛的美好时期全部用在了感叹人生上,只能在30岁的年纪重新扛起学业,活 ...

  8. ie浏览器报 promise 问题

    1.首先安装:babel-polyfill    npm install babel-polyfill --save2.然后引入:babel-polyfill 在build目录下,webpack.ba ...

  9. VmWare入门指南

    记得以前有大佬曾教过我们用win10的自带双系统运行Ubuntu,但这玩意儿好像玩起来并不简单(反正本人试了一上午也没成功),而且这个系统是和windows交互的,我们也很难调整性能参数.今天,我来教 ...

  10. 用Google Cloud Plateform使用ansible创建新实例

    谷歌大法好,退aws保平安 ---假设自己现在有一个电脑(本机),先用谷歌云创一个服务器(主机) ,再通过ansible在谷歌云上创建一个服务器(节点)并进行控制 先把自己的公钥加到元数据里面,在go ...