资讯专栏INFORMATION COLUMN

深入理解Java的整型类型:如何实现2+2=5?

aristark / 2344人阅读

摘要:先看下这段神奇的代码执行结果那么到底做了什么神奇的事情呢先看代码所以这个例子其实包含了中整型类型的一个知识点。最后打印出来的值,实际上是的返回值。只有当输入参数不在区间内,才执行代码,基于输入参数创建一个新的实例。

先看下这段神奇的Java代码:

public static void main(String[] args) throws Exception {

      doSomethingMagic();

      System.out.printf("2 + 2 = %d", 2 + 2);

}

执行结果:2 + 2 = 5

那么doSomethingMagic到底做了什么神奇的事情呢?先看代码:

private static void doSomethingMagic() throws Exception {

   Class cache = Integer.class.getDeclaredClasses()[0];

   Field c = cache.getDeclaredField("cache");

   c.setAccessible(true);

   Integer[] array = (Integer[]) c.get(cache);

   array[132] = array[133];

}

所以这个例子其实包含了Java中整型类型Integer的一个知识点。

可能有的朋友对于doSomethingMagic里面的代码有点摸不着头脑,让我们先查看上图第17行 2 + 2反编译出来的代码:

编辑器将2+ 2的值先计算出来,等于4。最后System.out.println打印出来的值,实际上是Integer.valueOf(4)的返回值。

那么我们就查看JDK里Integer.valueOf的实现:

上面的实现代码,从830行到832行,逻辑非常清楚:如果valueOf的参数i在IntegerCache.low和IntegerCache.high之间,即[-128, 127]的闭区间,则直接从IntegerCache这个缓存区域里返回。只有当输入参数i不在[-128,127]区间内,才执行代码832,基于输入参数i创建一个新的Integer实例。

带着这个理念,我们再看doSomethingMagic就清楚多了。这个方法通过Java反射将上图IntegerCache的成员cache设置成可访问:setAccessible(true), 然后将IntegerCache的第132个元素的值用第133个元素的值覆盖。

我们从Eclipse调试器里发现,Integer cache里第132个元素的值为4,第133个元素的值为5。本来Integer.valueOf方法,对于输入4,从Integer cache里返回第132个元素的值,即4。现在这个元素的值被第133个元素即5覆盖了,所以最后得到了 2 + 2 = 5。

用一句话概括这个场景: 2 + 2 = 4 = Integer.valueOf(4) = 5 ( 因为4在Integer cache里对应的记录已经被我们的代码显式替换成了5)。

要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71818.html

相关文章

  • 【C语言基础之类型转换】

    摘要:类型转换的原则占用内存字节数少值域小的类型,向占用内存字节数多值域大的类型转换,以保证精度不降低。隐式类型转换隐式转换也称为自动转换,遵循一定的规则,由编译器自动完成。 ...

    jsliang 评论0 收藏0
  • 一文读懂 Java 中的原子类

    摘要:一无锁方案并发包中的原子类都是基于无锁方案实现的,相较于传统的互斥锁,无锁并没有加锁解锁线程切换的消耗,因此无锁解决方案的性能更好,同时无锁还能够保证线程安全。线程首先读取的值并加,如果此时有另一个线程更新了,则期望值和不相等,更新失败。 一、无锁方案 Java 并发包中的原子类都是基于无锁方案实现的,相较于传统的互斥锁,无锁并没有加锁、解锁、线程切换的消耗,因此无锁解决方案的性能更好...

    jas0n 评论0 收藏0
  • Java 关键字专题

    摘要:和也许看起来像是关键字,但是他们专门用于表示布尔类型的字面量。值得注意的是,在中整形值和布尔值之间不能相互转换至少在语言层面。相关的操作等于不等于取反位与异或或条件与条件或三目运算符在控制流程中使用一个布尔值可且仅可被转型为,类型。 总览 Java 语言中有 50 个关键字,这些关键字不能用作标识符,如下图所示(来自 jls8) showImg(https://segmentfault...

    Dogee 评论0 收藏0
  • 【C语言初阶】❤️ 教你使用C语言中的各种操作符(熟练运用+必须收藏)❤️

    本章目录 温馨提示本章重点正文开始1. 操作符分类2.算数操作符2.1 `/`操作符2.2 `%`操作符 3. 位移操作符3.1 ``左移操作符 4. 位操作符4.1 `&`按位与操作符4.2 `|`按位或操作符4.3 `^`按位异或操作符 5. 赋值操作符6. 单目操作符6.1 各种单目操作符6.2 sizeof 和 数组 7. 关系操作符(后面的操作符不单独出现在目录中)8. ...

    source 评论0 收藏0
  • 深入理解HashMap(二): 关键源码逐行分析之hash算法

    摘要:散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值,,,或的指纹。 前言 系列文章目录 前面我们讨论了HashMap的结构, 接下来几篇我们从源码角度来看HashMap的实现细节. 本篇我们就来聊聊HashMap的hash算法 本文的源码基于 jdk8 版本. hash算法 上一篇文章我们提到, 为了利用数组索引进行快速查...

    chunquedong 评论0 收藏0

发表评论

0条评论

aristark

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<