五月的深圳空气中弥漫起初夏的味道,淡淡的,暖暖的。春日里不太张扬的阳光也掺入这股气息...(烟哥好文采!)

这天,烟哥愉快的喝着霸气芝士莓莓莓。一边东张西望,寻找着可以装13的机会。一切正如下面这张图这样



这时,小刘出现了!没错,就是那个大家期待的小刘出现了!她拿着一本《XXXjava笔试指南》来找烟哥。

只见小刘娴熟的打开这本书,望着整本书满满的笔记,烟哥不禁猜测道:"小刘如此热衷于学习,一定还是单身。"想到这里,烟哥不禁更有回答的动力了(没错,我就是这种人!)。

缓存问题

小刘翻到某一页后,指出下面这样一道题

  1. public static void main(String[] args){
  2. Integer a = 50;
  3. Integer b = 50;
  4. Integer c = 150;
  5. Integer d = 150;
  6. System.out.println(a==b);
  7. System.out.println(c==d);
  8. }

输出结果为

  1. true
  2. false

然后询问烟哥具体缘由。

烟哥看完以后,内心正(wei)直(suo)的笑了笑,心里想道:"这不是几年前的老题目了么,怎么现在还在考!"

烟哥回答道:"其实很简单,原理是下面这样滴!"

JAVA编译器编译Integer a = 50的时候,被翻译成-> Integer a = Integer.valueOf(50);

valueOf的源码是下面这样的

  1. public static Integer valueOf(int i) {
  2. if (i >= IntegerCache.low && i <= IntegerCache.high)
  3. return IntegerCache.cache[i + (-IntegerCache.low)];
  4. return new Integer(i);
  5. }

看到了嘛,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函数的源码,如下所示"

  1. public static int abs(int a) {
  2. return (a < 0) ? -a : a;
  3. }

烟哥:"看了源码,其实很明显,绝对值运算的原理是判断这个数是否大于零,如果小于零则取负值。OK,回到我们题目。Integer.MIN_VALUE,它的十六进制表示是 0x80000000。其符号位为1,其余所有的位都是0。取负数(反码+1)则为 0x7fffffff+1,也就是 0x80000000。你会发现对Integer.MIN_VALUE取负值还是本身。因此,结果还是负数。"

小刘:"那你这套理论对LongShortByte都成立么?"

烟哥:"是的,都是成立的,原理都一样。你可以回去测试一下如下代码"

  1. Short num =(short)Math.abs(Short.MIN_VALUE));
  2. 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"

  1. double i = Double.POSITIVE_INFINITY;
  2. System.out.println(i == i+1);

小刘反怼烟哥,说道:"其实,无穷大减去一个常数也是无穷大。所以下面例子也是输出为true,而且无穷小也有类似的特性。"

  1. double i = Double.POSITIVE_INFINITY;
  2. System.out.println(i == i-1);

烟哥满意的点了点头,感慨小刘成长真快!

突然,灵光一闪,烟哥补充道:"你知不知道有一个数可以满足i!=i?"

小刘再次陷入了深思...嘴里嘟囔道:"奇怪,还有一个数可以自己不等于自己么?"

望着小刘愁眉苦脸的眼神 ,烟哥答道:"对,有一个不是数值的值,它就是NaN,翻译过来就是(Not a Number),因此下面的输出是为true!"

  1. double i = Double.NaN;
  2. System.out.println(i != i);

结局

在烟哥一阵装13后,决定暴露自己的本性。问道:"小刘,你有对象了么?"

小刘答道:"烟哥,你是个好人,然而我已经有对象了!"

"Boom!"



(本文完!)

【原创】JAVA中令人眼花撩乱的数字魔法的更多相关文章

  1. Java中过滤出字母、数字和中文的正则表达式

    1.Java中过滤出字母.数字和中文的正则表达式 (1)过滤出字母的正则表达式 [^(A-Za-z)] (2)过滤出数字的正则表达式 [^(0-9)] (3)过滤出中文的正则表达式 [^(\\u4e0 ...

  2. AJPFX总结关于Java中过滤出字母、数字和中文的正则表达式

    1.Java中过滤出字母.数字和中文的正则表达式 (1)过滤出字母的正则表达式      [^(A-Za-z)] (2) 过滤出 数字 的正则表达式   [^(0-9)] (3) 过滤出 中文 的正则 ...

  3. (转载)java中判断字符串是否为数字的方法的几种方法

    java中判断字符串是否为数字的方法: 1.用JAVA自带的函数 public static boolean isNumeric(String str){ for (int i = 0; i < ...

  4. 字符串--java中判断字符串是否为数字的方法的几种方法?

    ava中判断字符串是否为数字的方法: 1.用JAVA自带的函数 public static boolean isNumeric(String str){ for (int i = 0; i < ...

  5. JAVA中令人疑惑的字符串

    Java中不同的字符串存在于同一个存储池中,字符串变量将指向存储池中相应的位置,也就是字符串变量里面包含的并不是字符串而是这个字符串对象的内存地址. String a = "123" ...

  6. java中判断字符串是否为数字的方法的几种方法

    1.用JAVA自带的函数 public static boolean isNumeric(String str){ for (int i = 0; i < str.length(); i++){ ...

  7. java中Number Type Casting(数字类型强转)的用法

    4.5 Number Type Casting(数字类型强转)隐式 casting(from small to big) byte a = 111; int b = a;显式 casting(from ...

  8. [原创]Java中的字符串比较,按照使用习惯进行比较

    java中的字符串比较一般可以采用compareTo函数,如果a.compareTo(b)返回的是小于0的数,那么说明a的unicode编码值小于b的unicode编码值. 但是很多情况下,我们开发一 ...

  9. Java中判断字符串是否为数字

    转载:https://blog.csdn.net/u013066244/article/details/53197756 用JAVA自带的函数 public static boolean isNume ...

随机推荐

  1. Android6.0权限管理以及使用权限该注意的地方

    Android 6.0 Marshmallow首次增加了执行时权限管理,这对用户来说,能够更好的了解.控 制 app 涉及到的权限.然而对开发人员来说却是一件比較蛋疼的事情.须要兼容适配,并保证程序功 ...

  2. UI_Target/action 设计模式

    RootView.m 中 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; button.frame = CGRectM ...

  3. 【转载】TCP的三次握手(建立连接)和四次挥手(关闭连接)

    建立连接: 理解:窗口和滑动窗口TCP的流量控制 TCP使用窗口机制进行流量控制 什么是窗口? 连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端 接收方发送的确认信息中包 ...

  4. cocos2d-x触摸事件优先级

     CCTouchDispatcher是管理cocos2d-x中全部Touch事件派发的类, CCTouchDispatcher中包括了两个CCTouchHandler的列表, 分别存储Standa ...

  5. ios开发之自己定义默认生成的导航栏 标题 颜色 返回button

    一 改动导航栏颜色    导航栏在哪个页面代码放在那里面 self.navigationController.navigationBar.tintColor = [UIColor colorWithR ...

  6. 利用python暴力破解ssh

    # -*- coding:utf-8 -*- #python 2.7 import optparse,sys,threading import pexpect PROMPT = ['#','>' ...

  7. (转)使用MAT比较多个heap dump文件

    使用MAT比较多个heap dump文件 调试内存泄露时,有时候适时比较2个或多个heap dump文件是很有用的.这时需要生成多个单独的HPROF文件. 下面是一些关于如何在MAT里比较多个heap ...

  8. MySQL优化之——触发器

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46763665 触发器是一个特殊的存储过程,不同的是存储过程要用CALL来调用,而触 ...

  9. svgo

    SVG精简压缩工具svgo简介和初体验 SVG精简压缩工具svgo简介和初体验 « 张鑫旭-鑫空间-鑫生活 https://www.zhangxinxu.com/wordpress/2016/02/s ...

  10. 轮廓线DP:poj 2279 Mr. Young's Picture Permutations

    poj 2279 Mr. Young's Picture Permutations \(solution:\) 首先摘取一些关键词:(每行不超过它后面的行)(每排学生安排高度从左到右减少)(学生的高度 ...