`

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)实现的,那么自动拆箱是如何实现的呢?
分享到:
评论

相关推荐

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

    在阅读博客文章《Java迷题:等于,还是不等于?》时,你可能会发现更多关于这个话题的深入讨论,包括在特定场景下的最佳实践和陷阱。通过不断学习和实践,我们可以提升自己的编程技能,避免常见的错误,从而提高代码...

    《Java迷题解惑》PDF

    有意思的一本书,都是有点难度且又比较有意思的JAVA问题,比如表达式奇数性解惑、找零时刻、长整除、十六进制的趣数等等,特别是这本书的语言也很会激起我们的兴趣,先从实际生活中的故事说起,然后了解所需,最后用...

    java迷题

    Java中的String对象是不可变的,这意味着每次对String进行修改都会创建新的对象,这可能导致不必要的内存消耗。为避免这个问题,可以使用StringBuilder或StringBuffer类在需要多次修改字符串时。 3. null引用异常...

    java 解惑 挺多java方面的迷题

    为了解决这个问题,我们可以修改条件判断,使其比较`i % 2`是否不等于0,这样就能正确处理负数和正数的情况。此外,如果性能是关键因素,可以使用位操作符`&`代替取余操作符,以提高效率: ```java public static ...

    java试题精选(带有参考答案)

    Java是一种广泛使用的面向对象的编程语言,以其跨平台、高性能和丰富的类库而著名。这份“java试题精选”显然旨在帮助学习者检验和提升他们的Java编程技能。试题通常包括基础语法、面向对象概念、异常处理、集合框架...

    Java的终极迷题及答案

    这次Java SE的开发工具( JDK )包括了有利于开发applet和应用程序的Java运行环境( JRE环境)及命令行开发工具。 此更新版本的完整内部版本号是1.6.0_10 - b33。外部版本

    java期末考题&Dreamweaver试题

    Java和Dreamweaver是两种截然不同的技术,但它们都在IT行业中扮演着重要的角色。Java是一种广泛使用的编程语言,而Dreamweaver则是Adobe公司开发的一款专业网页设计与开发工具。 在"java期末考题"中,我们可以期待...

    java基础入门教程

    香 港 则 在 今 年 4月 就 举 行 了 全 岛 的 Java杯 比 赛 ,在 计 算 机界掀 起 了 学 习 Java的热 潮 (尤 其 是 在 大 学 生 们 中 ,出 现 了 一 批 Java迷 )。 有 人 预 言 :Java将 是 网 络 上 的 "世 界 语 ...

    计算机等级考试Java强化测试题及参考答案.docx

    计算机等级考试是对个人在计算机相关领域知识和技能的评估,对于Java编程语言的测试,它涵盖了语言基础、类和对象、输入输出、事件处理等多个方面。以下是对文档中提到的一些关键知识点的详细解释: 1. **字符流**...

    八数码算法java实现

    为了测试和验证这个Java实现,可能包含了一系列的测试用例,包括但不限于初始状态和目标状态已知的情况,以及一些具有挑战性的迷题。这有助于确保算法的正确性和效率。 总的来说,这个Java项目不仅展示了如何使用...

    Java-Algorithm:算法培训项目

    在"Java-Algorithm:算法培训项目"中,我们主要探讨如何使用Java编程语言来实现各种经典的算法。这个项目旨在帮助开发者提升对算法的理解,增强编程技巧,并能够熟练地运用Java进行算法设计与分析。 首先,我们要...

    aiyinsitan.rar_Java 8_aiyinsitan_java smoke_jmonkey_脑筋

    原题为: 1.有5栋5种颜色的房子 2.每一位房子的主人国籍都不同 ... 这道迷题出自1981年柏林的德国逻辑思考学院。 据说世界上只有2%的人能出答案。 就连大名鼎鼎的爱因斯坦也成为此题大伤脑筋。

    数据结构与算法java版.rar

    本书提供了学习经典数据结构和算法的新方法。通过带有完整工作代码的详细示例清晰、透彻地解释了全书内容。掷骰子、纸牌和棋盘游戏提供了大量新颖、迷人的示例。 本书首先透彻介绍了面向对象程序设计。利用这些工具...

    万得信息技术Java开发面经.pdf

    场景题:集群服务器宕机解决⽅案 8.MongoDB和redis区别,分别何时使⽤,MongoDB讲⼀下 9.完全平衡⼆叉树简述,红⿊树简述 10.mysql引擎底层 11.索引优化(什么时候⽤索引,什么时候不能⽤) 12.索引⼯作流程 13....

    java变量作用域笔试题-arquillian-testrunner-spock:ArquillianSpockTestRunner

    java引发作用域笔试题Spock Arquillian 扩展 在容器中进行 BDD 测试! 它是什么? Arquillian 是在 JBoss.org 开发的测试框架,它使开发人员能够为在嵌入式或远程容器内执行的业务对象编写集成测试——选项包括 ...

    初级java笔试题-nand2tetris:nand2tetris.org课程的解决方案

    初级java笔试题nand2tetris.org 第 1 部分课程文件和答案 课程详情 Nand to Tetris 课程将带您进行自定进度的迷人发现之旅,您将一路从布尔代数和基本逻辑门到构建中央处理单元、存储系统和硬件平台,直至一台可以...

    leetcode第四题-rprater:代理

    第四题工程师和研究迷 我目前正在瑞尔森大学学习工程学,同时正在寻找我的第四次也是最后一次实习。 另一方面,我构建了很酷的 Python 项目并研究了混沌理论。 跟我来这里 我喜欢研究的东西 编码和辅助项目 机器学习...

    华为OD题解,共计112道题

    文章作者参考了MISAYAONE提供的题库,并提供了自己的Java解决方案,力求简洁高效,同时也对原有的错误进行了校对。尽管如此,由于没有全部上机实践,不能保证所有代码都能100%通过。 这些题目与LeetCode平台上的...

    12月全国计算机二级考试考前复习点破.docx

    1. 分析错误原因,是因为知识点掌握不牢,还是解题策略不当。 2. 复习相关知识点,确保理解和记忆。 3. 重新做题,直到能够独立正确解答。 4. 定期进行模拟测试,保持对考试环境的适应性。 在复习过程中,考生还应...

Global site tag (gtag.js) - Google Analytics