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


    等于还是不等于?

    看来看下面的一段代码:

    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 }
    View Code

     这段代码的输出是什么?相信很多人都会很容易的猜到: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 }
    View Code

    你可能会回答,这没什么不一样啊,所以还是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 
    Code 3

     结果是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 }
    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方法的调用。那么另一次是哪里呢?只可能在自动装箱时调用的。因此这段代码实际上等价于:

    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 }
    View Code

     现在问题就简单了:看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 }
    View Code

    看到这儿,上面的代码就很明确了:对于-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 }
    View Code

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

     

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

     

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

    声明:

    文章来自于ITeye,欢迎访问我的博客:xiaoyu1985ban.iteye.com

    ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者。

  • 相关阅读:
    巴菲特最推崇的10本书
    如何锻炼剑术基本功
    Ubuntu 20.04 LTS, CUDA 11.2.0, NVIDIA 455 and libcudnn 8.0.4
    缘起性空
    Mac 每次都要执行source ~/.bash_profile 配置的环境变量才生效
    Calcite分析 -- Register
    go超时控制有4种写法,你知道吗?
    npm install node-sass报错处理
    IDEA + maven热部署及自动编译不生效问题
    1-STM32+CH395Q(以太网)远程升级篇(自建物联网平台)-STM32通过ch395使用http下载程序文件,升级程序(单片机程序轮训检查更新)
  • 原文地址:https://www.cnblogs.com/beibeibao/p/3410470.html
Copyright © 2020-2023  润新知