热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javashort相等_Java对象比较用==还是用“equals”,避坑方法~~

1.对象比较方法JDK1.7提供的Objects.equals方法,非常方便地实现了对象的比较,有效地避免了繁琐的空指针检查。1.1.问题现象在JDK1

1.对象比较方法

JDK1.7提供的Objects.equals方法,非常方便地实现了对象的比较,有效地避免了繁琐的空指针检查。

1.1.问题现象

在JDK1.7之前,在判断一个短整型、整型、长整型包装数据类型与常量是否相等时,我们一般这样写:

Short shortValue = (short)12345;

System.out.println(shortValue == 12345); // true

System.out.println(12345 == shortValue); // true

Integer intValue = 12345;

System.out.println(intValue == 12345); // true

System.out.println(12345 == intValue); // true

Long longValue = 12345L;

System.out.println(longValue == 12345); // true

System.out.println(12345 == longValue); // true

从JDK1.7之后,提供了Objects.equals方法,并推荐使用函数式编程,更改代码如下:

Short shortValue = (short)12345;

System.out.println(Objects.equals(shortValue, 12345)); // false

System.out.println(Objects.equals(12345, shortValue)); // false

Integer intValue = 12345;

System.out.println(Objects.equals(intValue, 12345)); // true

System.out.println(Objects.equals(12345, intValue)); // true

Long longValue = 12345L;

System.out.println(Objects.equals(longValue, 12345)); // false

System.out.println(Objects.equals(12345, longValue)); // false

为什么直接把==替换为Objects.equals方法会导致输出结果不一样?

1.2.问题分析

通过反编译第一段代码,我们得到语句"System.out.println(shortValue == 12345);"的字节码指令如下:

7   getstatic java.lang.System.out : java.io.PrintStream [22]

10  aload_1 [shortValue]

11  invokevirtual java.lang.Short.shortValue() : short [28]

14  sipush 12345

17  if_icmpne 24

20  iconst_1

21  goto 25

24  iconst_0

25  invokevirtual java.io.PrintStream.println(boolean) : void [32]

原来,编译器会判断包装数据类型对应的基本数据类型,并采用这个基本数据类型的指令进行比较(比如上面字节码指令中的sipush和if_icmpne等),相当于编译器自动对常量进行了数据类型的强制转化。

为什么采用Objects.equals方法后,编译器不自动对常量进行数据类型的强制转化?通过反编译第二段代码,我们得到语句"System.out.println(Objects.equals(shortValue, 12345));"的字节码指令如下:

7   getstatic java.lang.System.out : java.io.PrintStream [22]

10  aload_1 [shortValue]

11  sipush 12345

14  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [28]

17  invokestatic java.util.Objects.equals(java.lang.Object, java.lang.Object) : boolean [33]

20  invokevirtual java.io.PrintStream.println(boolean) : void [39]

原来,编译器根据字面意思,认为常量12345默认基本数据类型是int,所以会自动转化为包装数据类型Integer。在Java语言中,整数的默认数据类型是int,小数的默认数据类型是double。

下面来分析一下Objects.equals方法的代码实现:

Objects.equals方法的代码实现为:

public static boolean equals(Object a, Object b) {

return (a == b) || (a != null && a.equals(b));

}

其中,语句“a.equals(b)”将会使用到Short.equals方法。

Short.equals方法的代码实现为:

public boolean equals(Object obj) {

if (obj instanceof Short) {

return value == ((Short)obj).shortValue();

}

return false;

}

通过代码实现分析:对应语句"System.out.println(Objects.equals(shortValue,

12345));",因为Objects.equals的两个参数对象类型不一致,一个是包装数据类型Short,另一个是包装数据类型Integer,所以最终的比较结果必然是false。同样,语句“System.out.println(Objects.equals(intValue,

12345));”,因为Objects.equals的两个参数对象类型一致,都是包装数据类型Integer且取值一样,所以最终的比较结果必然是true。

1.3.避坑方法

(1)保持良好的编码习惯,避免数据类型的自动转化

为了避免数据类型自动转化,更科学的写法是直接声明常量为对应的基本数据类型。

第一段代码可以这样写:

Short shortValue = (short)12345;

System.out.println(shortValue == (short)12345); // true

System.out.println((short)12345 == shortValue); // true

Integer intValue = 12345;

System.out.println(intValue == 12345); // true

System.out.println(12345 == intValue); // true

Long longValue = 12345L;

System.out.println(longValue == 12345L); // true

System.out.println(12345L == longValue); // true

第二段代码可以这样写:

Short shortValue = (short)12345;

System.out.println(Objects.equals(shortValue, (short)12345)); // true

System.out.println(Objects.equals((short)12345, shortValue)); // true

Integer intValue = 12345;

System.out.println(Objects.equals(intValue, 12345)); // true

System.out.println(Objects.equals(12345, intValue)); // true

Long longValue = 12345L;

System.out.println(Objects.equals(longValue, 12345L)); // true

System.out.println(Objects.equals(12345L, longValue)); // true

(2)借助开发工具或插件,及早地发现数据类型不匹配问题

在Eclipse的问题窗口中,我们会看到这样的提示:



推荐阅读
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • MPLS VP恩 后门链路shamlink实验及配置步骤
    本文介绍了MPLS VP恩 后门链路shamlink的实验步骤及配置过程,包括拓扑、CE1、PE1、P1、P2、PE2和CE2的配置。详细讲解了shamlink实验的目的和操作步骤,帮助读者理解和实践该技术。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
  • 用Vue实现的Demo商品管理效果图及实现代码
    本文介绍了一个使用Vue实现的Demo商品管理的效果图及实现代码。 ... [详细]
author-avatar
黑白
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有