技术中心

这里象征着我们的态度和能力

>Java迷题:等于还是不等于?
作者:中国IT实验室    来源:中国IT实验室    发布时间:2012-03-12      浏览次数:6765
分享到:
欢迎进入Java社区论坛,与200万技术人员互动交流 >>进入
表面上看来这只是一些基础的问题,当真正的了解了以后你就会发现:啊,原来是这么一回事!下文是几道Java谜题,不仔细分析就会犯错哦。

  等于还是不等于?

  看来看下面的一段代码:

  代码片段1

  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); }

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

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

  代码片段4

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

  最后的结果,可能你已经猜到了,是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)实现的,那么自动拆箱是如何实现的呢?

4000-880-989
(24小时热线)
联系客服
微信公众号

官方公众号

小程序

©2008-2022 CORPORATION ALL Rights Reserved. 昆明奥远科技有限公司版权所有 滇ICP备09003328号-1 滇公网安备 53011102000818号 增值电信业务经营许可证号:滇B2-20110045
昆明那家网络公司好,新媒体运营,网站优化,网络推广,网站建设,网页设计,网站设计,网站推广,云南网站公司,昆明新媒体公司,云南网红主播,昆明SEO公司,昆明网站建设,昆明网络推广,昆明网站优化,昆明网站推广,红河网站建设,大理网络公司,曲靖网络公司,丽江网站设计,昭通网络公司,保山大数据服务,智慧高速建设,智慧校园服务,云南IDC服务商,网络安全测评,等保测评,网站关键词排名优化服务,服务客户尽超2000余家,一切尽在奥远科技,服务电话:13888956730