Java迷题:等于,还是不等于?
等于还是不等于?
看来看下面的一段代码:
public static void main(final String[] args) {
Integer a = new Integer(100);
Integer b = 100;
System.out.println(a == b);
}
这段代码的输出是什么?相信很多人都会很容易的猜到:false,因为a、b两个对象的地址不同,用“==”比较时是false。恭喜你,答对了。
再看下面的一段代码:
代码片段2
public static void main(final String[] args) {
Integer a = 100;
Integer b = 100;
System.out.println(a == b);
}
你可能会回答,这没什么不一样啊,所以还是false。很遗憾,如果你执行上面的一段代码,结果是true。
上面的代码可能让你有些意外,那好吧,再看看下面的这段代码:
代码片段3
public static void main(final String[] args) {
Integer a = 156;
Integer b = 156;
System.out.println(a == b);
Code 3
结果是true吗?很遗憾,如果你执行上面的一段代码,结果是false。
感到吃惊吗?那最后再看下面的一段代码:
代码片段4
public static void main(final String[] args) {
Integer a = Integer.valueOf(100);
Integer b = 100;
System.out.println(a == b);
}
Code 4
最后的结果,可能你已经猜到了,是true。
为什么会这样?
现在我们分析一下上面的代码。可以很容易的看出,这一系列代码的最终目的都是用“==”对两个对象进行比较。Java中,如果用“==”比较两个对象结果为true,说明这两个对象实际上是同一个对象,false说明是两个对象。
现在,我们来看看为什么会出现上面的现象。
我们先看代码片段4:最后的运行结果是true,说明a、b两个对象实际上是同一个对象。但是a对象是通过调用Integer的valueOf方法创建的,而b对象是通过自动装箱创建出来的,怎么会是同一个对象呢?难道问题在字节码那里,毕竟Java程序是依靠虚拟器运行字节码来实现的。
通过jdk中自带的工具javap,解析字节码,核心的部分摘取如下:
0: bipush 100
2: invokestatic #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
6: bipush 100
8: invokestatic #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
代码中我们只调用了一次Integer.valueOf方法,但是字节码中出现了两次对Integer.valueOf方法的调用。那么另一次是哪里呢?只可能在自动装箱时调用的。因此这段代码实际上等价于:
public static void main(final String[] args) {
Integer a = Integer.valueOf(100);
Integer b = Integer.valueOf(100);
System.out.println(a == b);
}
现在问题就简单了:看jdk源代码,查看valueOf方法的具体实现:
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
看到这儿,上面的代码就很明确了:对于-128到127的数字,valueOf返回的是缓存中的对象。所以两次调用Integer.valueOf(100)返回的都是同一个对象。
我们再先看代码片段3:根据上面的分析,代码片段3实际上等价于以下代码:
public static void main(final String[] args) {
Integer a = Integer.valueOf(156);
Integer b = Integer.valueOf(156);
System.out.println(a == b);
}
由于156不在-128到127范围内,所以两个对象都是通过new Integer()的方式创建的,所以最后结果为false。
片段1和片段2就不做具体分析了,相信读者可以自行分析。
最后,请大家思考一下问题:通过上面的分析,了解到整数的自动装箱是通过Integer.valueOf(int number)实现的,那么自动拆箱是如何实现的呢?
声明:
文章来自于ITeye,欢迎访问我的博客:xiaoyu1985ban.iteye.com
ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者。
Java迷题:等于,还是不等于?的更多相关文章
- Java中文字符处理的四大迷题
虽然计算机对英文字符的支持非常不错,我们也恨不得写的程序只会处理英文的数据,但是昨为中国人,无可避免地要处理一些中文字符.当很简单的一件事情,遇到了中文,一切就不同了!本文就会讲述实际生产环境中遇到的 ...
- 50道经典的JAVA编程题 (11-15)
50道经典的JAVA编程题 (11-15),新年的第一天,继续啦...\(^o^)/~,这50道题都跨年了啊...哈哈 [程序11] TestTN.java 题目:有1.2.3.4个数字,能组成多少个 ...
- 50道经典的JAVA编程题 (6-10)
50道经典的JAVA编程题 (6-10),今晚做了10道了,累死了...感觉难度不是很大,就是不知道是不是最好的实现方法啊!希望大神们能给指点哈... [程序6]GCDAndLCM.java 题目:输 ...
- 【原创】这道Java基础题真的有坑!我也没想到还有续集。
前情回顾 自从我上次发了<这道Java基础题真的有坑!我求求你,认真思考后再回答.>这篇文章后.我通过这样的一个行文结构: 解析了小马哥出的这道题,让大家明白了这题的坑在哪里,这题背后隐藏 ...
- mysql的基本查询(等于,不等于,between...and...,)
单个字段多个字段查询 查询员工姓名 *注:在SQL语句中不区分大小写:SQL语句以“:”分号结束 select ename from emp; 注:select询句后面跟的是字段名称,select是关 ...
- 50道经典的JAVA编程题(汇总)
这是一次不可思议的编程历程.从2013年的最后一天开始做这份题,中间连续好几天的考试,包括java考试(今天考试的JAVA编程题),直到今天完成了.挺有成就感的...废话不多说了,来电实质性的吧. 全 ...
- 50道经典的JAVA编程题(46-50)
50道经典的JAVA编程题(46-50),最后五道题了,这是一个美妙的过程,编程真的能让我忘掉一切投入其中,感觉很棒.今天下午考完微机原理了,大三上学期就这样度过了,这学期算是解放了,可是感觉我还是没 ...
- 50道经典的JAVA编程题(41-45)
50道经典的JAVA编程题(41-45),苦逼的程序猿,晚上睡不着了编程吧~今天坚持做10道题!发现编程能是我快乐...O(∩_∩)O哈哈~能平静我烦乱的心,剩下5道题留到考试完了再做吧!该睡觉了.. ...
- 今天考试的JAVA编程题
今天早上考了java, 题目感觉还不错, 共四道题,有一道定义类的没啥意思就没列出来. 这三道题目还是不错的,特别是第一道,大一上学期学linux的时候,那时还没学C语言呢,准确的来说,还不知道什么是 ...
随机推荐
- C#委托多播、Lambda表达、多线程、任务
class Program { static void Main(string[] args) { Action<double> ops = MathOperations.Mutiply; ...
- [Uva 10085] The most distant state (BFS)
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- ubuntu实用技巧
添加alias ~/.bash_alias文件: alias go="python /Users/xhat/Downloads/goagent/local/proxy.py" ~/ ...
- (转)配置Website的IIS时遇到的问题与解决方法
在部署WebSite时遇到问题,刚好发现Eric Sun的文章,因此转载做个副本. 原文地址:http://www.cnblogs.com/mingmingruyuedlut/archive/2011 ...
- MySQL数据库优化技术概述
对于一个以数据库为中心的应用,数据库的优化直接影响到程序的性能,因此数据库性能至关重要.一般来说,要保证数据库的效率,要做好以下几个方面的工作: 1. 数据库表设计: 表的设计合理化(符合3NF): ...
- SQL Server int类型值最大2147483647(2^31 - 1)
突发奇想,一个字增字段,假设每天增加1000条记录,多少年之后写不进int类型的字段了2147483647 / 1000 / 365 = 5883.51684109589041095890410958 ...
- 在 ASP.NET MVC 应用中使用 NInject 注入 ASMX 类型的 Web Service
这几天,有同学问到为什么在 ASP.NET MVC 应用中,无法在 .ASMX 中使用 NInject 进行注入. 现象 比如,我们定义了一个接口,然后定义了一个实现. public interfac ...
- 数据结构-多级指针单链表(C语言)
偶尔看到大一时候写了一个多级链表,听起来好有趣,稍微整理一下. 稍微注意一下两点: 1.指针是一个地址,他自己也是有一个地址.一级指针(带一个*号)表示一级地址,他自身地址为二级地址.二级指针(带两个 ...
- ICE学习——异步1
ICE的AMI和AMD: AMI:指的是客户端的调用.一般有一个代理类,一个回调类. 从服务端返回的数据在回调类中的ice_response函数中. AMD:指的是服务端对客户端的调用分派.一般进行业 ...
- django中添加用户
在django中添加用户,直接在auth_user表中添加会有问题,因为这里密码是加密的,可以通过manage.py shell加入 创建User: 1 >>> from djang ...