五月的深圳空气中弥漫起初夏的味道, 淡淡的, 暖暖的. 春日里不太张扬的阳光也掺入这股气息...(烟哥好文采!)
这天, 烟哥愉快的喝着霸气芝士莓莓莓. 一边东张西望, 寻找着可以装 13 的机会. 一切正如下面这张图这样
这时, 小刘出现了! 没错, 就是那个大家期待的小刘出现了! 她拿着一本《XXXjava 笔试指南》来找烟哥.
只见小刘娴熟的打开这本书, 望着整本书满满的笔记, 烟哥不禁猜测道:"小刘如此热衷于学习, 一定还是单身." 想到这里, 烟哥不禁更有回答的动力了(没错, 我就是这种人!).
缓存问题
小刘翻到某一页后, 指出下面这样一道题
- public static void main(String[] args){
- Integer a = 50;
- Integer b = 50;
- Integer c = 150;
- Integer d = 150;
- System.out.println(a==b);
- System.out.println(c==d);
- }
输出结果为
true false
然后询问烟哥具体缘由.
烟哥看完以后, 内心正 (wei) 直(suo)的笑了笑, 心里想道:"这不是几年前的老题目了么, 怎么现在还在考!"
烟哥回答道:"其实很简单, 原理是下面这样滴!"
JAVA 编译器编译 Integer a = 50 的时候, 被翻译成 -> Integer a = Integer.valueOf(50);
而 valueOf 的源码是下面这样的
- public static Integer valueOf(int i) {
- if (i>= IntegerCache.low && i <= IntegerCache.high)
- return IntegerCache.cache[i + (-IntegerCache.low)];
- return new Integer(i);
- }
看到了嘛, Integer 内部有一个 IntegerCache 缓存. 对于值范围在 - 128 到 127 之间的数, 会进行缓存. 因此 a 和 b 范围在 - 128 到 127 之间, 所以指向的是同一个对象, 所以判断结果是 true. 而 c 和 d 在 128 之外, 所以每次都是返回一个新对象, 所以判断结果是 false.
听到这里, 小刘似乎很满意的准备打道回府.
"不行, 怎么能这样让小刘离开. 我得多和小刘说说话!"
于是, 烟哥说道:"小刘阿, 其实 java 笔试里关于数值方面的陷阱, 可以玩出很多花样, 你了解多少?"
很自然的, 小刘的表情是下面这样的
越界问题
烟哥说道:"这样吧, 先问你一个问题. Math.abs(Integer.MIN_VALUE))的结果是正数还是负数?"
小刘:"Math.abs 是绝对值运算, 结果应该是正数吧."
烟哥:"不对, 还是负数. Integer 的范围为 - 2147483648~2147483647. 不过我们先来看一眼 abs 函数的源码, 如下所示"
- public static int abs(int a) {
- return (a < 0) ? -a : a;
- }
烟哥:"看了源码, 其实很明显, 绝对值运算的原理是判断这个数是否大于零, 如果小于零则取负值. OK, 回到我们题目. Integer.MIN_VALUE, 它的十六进制表示是 0x80000000. 其符号位为 1, 其余所有的位都是 0. 取负数 (反码 + 1) 则为 0x7fffffff+1, 也就是 0x80000000. 你会发现对 Integer.MIN_VALUE 取负值还是本身. 因此, 结果还是负数."
小刘:"那你这套理论对 Long,Short,Byte 都成立么?"
烟哥:"是的, 都是成立的, 原理都一样. 你可以回去测试一下如下代码"
- Short num =(short)Math.abs(Short.MIN_VALUE));
- System.out.println(num);
小刘望着这些代码, 陷入了思考...
突然, 小刘回答道:"好像, 之前我有看到一个题目是这样的. 是否存在一个数 i, 可以使得 i+1<i, 这样看来, 这个 i 就是 Integer.MAX_VALUE, 因为加完 1 就溢出了变为负值了."
听小刘说道这里, 烟哥换了一个角度问:"是否存在一个数, 满足 i != 0 && i == -i"
小刘想了下, 机智的回答道:"其实还是 Integer.MIN_VALUE, 原因你刚才说过了!"
唉, 没想到小刘领悟如此的快!
浮点奥秘
烟哥感慨小刘领悟速度的同时, 加大难度问道:"是否存在一个数, 满足 i==i+1?"
小刘突然懵了, 答道:"好像.. 似乎.. 应该一个数永远不会等于自己加一."
看见小刘懵圈的眼神, 烟哥只见自己装 13 的目的已经达到, 便不再卖关子...
烟哥回答道:"有没听过一句话, 无穷大加一个常数还是无穷大! 所以, 下面的例子输出为 true"
- double i = Double.POSITIVE_INFINITY;
- System.out.println(i == i+1);
小刘反怼烟哥, 说道:"其实, 无穷大减去一个常数也是无穷大. 所以下面例子也是输出为 true, 而且无穷小也有类似的特性."
- double i = Double.POSITIVE_INFINITY;
- System.out.println(i == i-1);
烟哥满意的点了点头, 感慨小刘成长真快!
突然, 灵光一闪, 烟哥补充道:"你知不知道有一个数可以满足 i!=i?"
小刘再次陷入了深思... 嘴里嘟囔道:"奇怪, 还有一个数可以自己不等于自己么?"
望着小刘愁眉苦脸的眼神 , 烟哥答道:"对, 有一个不是数值的值, 它就是 NaN, 翻译过来就是(Not a Number), 因此下面的输出是为 true!"
- double i = Double.NaN;
- System.out.println(i != i);
结局
在烟哥一阵装 13 后, 决定暴露自己的本性. 问道:"小刘, 你有对象了么?"
小刘答道:"烟哥, 你是个好人, 然而我已经有对象了!"
"Boom!"
(本文完!)
来源: https://www.cnblogs.com/rjzheng/p/10910834.html