Java迷题:等于,还是不等于?

等于还是不等于?

创新互联建站专业为企业提供什邡网站建设、什邡做网站、什邡网站设计、什邡网站制作等企业网站建设、网页设计与制作、什邡企业网站模板建站服务,十多年什邡做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

看来看下面的一段代码:

代码片段1

 
 
 
  1. public static void main(final String[] args) {    
  2.     Integer a = new Integer(100);    
  3.     Integer b = 100;    
  4.     System.out.println(a == b);     
  5. }   

这段代码的输出是什么?相信很多人都会很容易的猜到:false,因为a、b两个对象的地址不同,用“==”比较时是false。恭喜你,答对了。

再看下面的一段代码:

代码片段2

 
 
 
  1. public static void main(final String[] args) {    
  2.     Integer a = 100;    
  3.     Integer b = 100;    
  4.     System.out.println(a == b);     
  5. }   

你可能会回答,这没什么不一样啊,所以还是false。很遗憾,如果你执行上面的一段代码,结果是true。

上面的代码可能让你有些意外,那好吧,再看看下面的这段代码:

代码片段3

 
 
 
  1. public static void main(final String[] args) {    
  2.     Integer a = 156;    
  3.     Integer b = 156;    
  4.     System.out.println(a == b);     
  5. }   

结果是true吗?很遗憾,如果你执行上面的一段代码,结果是false。

感到吃惊吗?那最后再看下面的一段代码:

代码片段4

 
 
 
  1. public static void main(final String[] args) {    
  2.     Integer a = Integer.valueOf(100);    
  3.     Integer b = 100;    
  4.     System.out.println(a == b);     
  5. }   

最后的结果,可能你已经猜到了,是true。

为什么会这样?

现在我们分析一下上面的代码。可以很容易的看出,这一系列代码的最终目的都是用“==”对两个对象进行比较。Java中,如果用“==”比较两个对象结果为true,说明这两个对象实际上是同一个对象,false说明是两个对象。

现在,我们来看看为什么会出现上面的现象。

我们先看代码片段4:最后的运行结果是true,说明a、b两个对象实际上是同一个对象。但是a对象是通过调用Integer的valueOf方法创建的,而b对象是通过自动装箱创建出来的,怎么会是同一个对象呢?难道问题在字节码那里,毕竟Java程序是依靠虚拟器运行字节码来实现的。

通过jdk中自带的工具javap,解析字节码,核心的部分摘取如下:

 
 
 
  1. 0:  bipush  100    
  2. 2:  invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;    
  3. 5:  astore_1    
  4. 6:  bipush  100    
  5. 8:  invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   

代码中我们只调用了一次Integer.valueOf方法,但是字节码中出现了两次对Integer.valueOf方法的调用。那么另一次是哪里呢?只可能在自动装箱时调用的。因此这段代码实际上等价于:

 
 
 
  1. public static void main(final String[] args) {    
  2.     Integer a = Integer.valueOf(100);    
  3.     Integer b = Integer.valueOf(100);    
  4.     System.out.println(a == b);     
  5. }   

现在问题就简单了:看jdk源代码,查看valueOf方法的具体实现:

 
 
 
  1. public static Integer valueOf(int i) {    
  2.     final int offset = 128;    
  3.     if (i >= -128 && i <= 127) { // must cache     
  4.         return IntegerCache.cache[i + offset];    
  5.     }    
  6.     return new Integer(i);    
  7. }   

看到这儿,上面的代码就很明确了:对于-128到127的数字,valueOf返回的是缓存中的对象。所以两次调用Integer.valueOf(100)返回的都是同一个对象。

我们再先看代码片段3:根据上面的分析,代码片段3实际上等价于以下代码:

 
 
 
  1. public static void main(final String[] args) {    
  2.     Integer a = Integer.valueOf(156);    
  3.     Integer b = Integer.valueOf(156);    
  4.     System.out.println(a == b);     
  5. }   

由于156不在-128到127范围内,所以两个对象都是通过new Integer()的方式创建的,所以最后结果为false。

片段1和片段2就不做具体分析了,相信读者可以自行分析。

最后,请大家思考一下问题:通过上面的分析,了解到整数的自动装箱是通过Integer.valueOf(int number)实现的,那么自动拆箱是如何实现的呢?

原文链接:http://www.blogjava.net/todayx-org/archive/2012/02/01/369115.html

【编辑推荐】

  1. Java数据库连接代码集合
  2. Java之线程池简单实现
  3. Java回调函数的理解
  4. Java路线图:甲骨文的两年计划
  5. Java Thread的概述与总结

分享文章:Java迷题:等于,还是不等于?
文章URL:http://www.shufengxianlan.com/qtweb/news46/298196.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联