五月的深圳空气中弥漫起初夏的味道,淡淡的,暖暖的。春日里不太张扬的阳光也掺入这股气息...(烟哥好文采!)
这天,烟哥愉快的喝着霸气芝士莓莓莓。一边东张西望,寻找着可以装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!\"
(本文完!)