java byte 判断相等_你真的了解Java中quot;==quot;和equals()的区别?

d86b0468e4daf81015b9c2829892e4f0.png

部分面试资料链接:https://pan.baidu.com/s/1qDb2YoCopCHoQXH15jiLhA

密码:jsam

想获得全部面试必看资料,关注公众号,大家可以在公众号后台回复“知乎”即可。

617a3a64402cec13f4dce4d2ddd19d5d.png

499c34618bb98f211912a85dc1eb884b.png

“判断两个事物是否相等”,是编程中最常见的操作之一,在Java中,判断是否相等有两种方法,一种是使用“==”判断符,另一种是使用“equals()”方法,你是否曾因混用二者导致不可思议的bug?本篇文章将带你深入二者背后的判断原理。

相等判断符"=="

"=="相等判断符用于比较基本数据类型和引用类型数据。当比较基本数据类型的时候比较的是数值,当比较引用类型数据时比较的是引用(指针)。

"=="判断基本类型数据

基本数据类型指的是Java中的八大数据类型:byte,short,int,long,float,double,char,boolean。

这八大基本数据类型有个共同的特点是它们在内存中是有具体值的, 比如说一个 int 类型的数据"2",它在8位数据总线的机器上保存形式为 0000 0010。(8位机器是假设的)

当使用 == 比较两个基本数据类型的时候, 就是在比较它们各自在内存中的值。

为了照顾到要刨根问底的同学,再补充一下两个数值是怎么比较的:cpu 在比较的时候会将两个值作差,然后查看标志寄存器。标志寄存器存放的是运算的结果,里面有一个是否为0的标志位,如果该位为1,证明二者之差为0,二者相等。

"=="判断引用类型数据

引用数据类型在字面上也是很好理解的, 它就是一个引用, 指向堆内存中一个具体的对象。

比如说Student stu = new Student(); 这里的 stu 就是一个引用,它指向的是当前 new 出来的 Student 对象. 当我们想要操作这个 Student 对象时, 只需要操作引用即可, 比如说int age = stu.getAge();

所以用"=="判断两个引用数据类型是否相等的时候,实际上是在判断两个引用是否指向同一个对象

看下面的示例:

public static void main(String[] args) {String s1 = "hello";    //s1指向字符串常量池中的"hello"字符串对象String s2 = "hello";    //s2也指向字符串常量池中的"hello"字符串对象System.out.println(s1 == s2);   //trueString s3 = new String("hello");   //s3指向的是堆内存中的字符串对象 System.out.println(s1 == s3);    //false
}

从上面的例子可以看到,由于引用"s1"和"s2"指向的都是常量池中的"hello"字符串,所以返回true。(后面我会发布一篇详细讲述Java字符串的文章,涉及字符串初始化和字符串常量池等知识)

而"s3"指向的是新创建字符串对象,因为只要动用了new关键字, 就会在堆内存创建一个新的对象。

也就是说 s1 和 s3 指向的是不同的字符串对象,所以返回false。

相等判断方法equals()

equals()和 == 有着本质的区别,== 可以看作是对“操作系统比较数据手段”的封装,而equals()则是每个对象自带的比较方法,它是Java自定义的比较规则。

equals()和 == 的本质区别更通俗的说法是:==的比较规则是定死的,就是比较两个数据的值。

而 equals() 的比较规则是不固定的,可以由用户自己定义。

看下面的例子:

public static void main(String[] args) {String s1 = "hello";String s3 = new String("hello");    System.out.println(s1.equals(s3));    //true
}

回想前面的案例:用 == 比较的时候, 上面 s1 和 s3 比较出的结果为false。而当用 equals() 比较的时候,得出的结果为 true。

想知道原因我们还得看源码,下面是 String 类中的 equals() 方法的源码。

public boolean equals(Object anObject) {if (this == anObject) {    //先比较两个字符串的引用是否相等(是否指向同一个对象), 是直接返回truereturn true;}if (anObject instanceof String) {    //两个引用不等还会继续比较String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;    //字符串类是用字符数组实现的, 先要拿到两个字符串的字符数组char v2[] = anotherString.value;int i = 0;while (n-- != 0) {    //然后对两个数组逐个字符地进行比较if (v1[i] != v2[i])return false;i++;}return true;}}return false;
}

从上面的源码可以看到, 当调用 String 类型数据的 equals() 方法时,首先会判断两个字符串的引用是否相等,也就是说两个字符串引用是否指向同一个对象,是则返回true。

如果不是指向同一个对象,则把两个字符串中的字符挨个进行比较。由于 s1 和 s3 字符串都是 "hello",是可以匹配成功的,所以最终返回 true。

思考:为什么要设计equals()方法?

通过上面的讲解,相信你已经知道 == 和 equals() 的区别了:一个的比较规则是定死的,一个是可以由编程人员自己定义的。

可是为什么会有 equals() 方法, 而且还可以被自由定制呢?

这个问题要落到Java语言的核心 —— 面向对象思想了。

Java 不同于面向过程的C语言,Java是一款面向对象的高级语言。如果是面向过程编程,直接操作内存上存储的数据的话,用 == 所定义的规则来判断两个数据是否相等已经足够了。

而Java中万物皆对象,我们经常要面临的问题是这两个对象是否相等,而不是这两串二进制数是否相等,仅有 == 是完全不够用的。

由于Java程序员们会创建各种满足它们业务需求的对象,系统无法提前知道两个对象在什么条件下算相等,Java干脆把判断对象是否相等的权力交给编程人员

具体的措施是:所有的类都必须继承 Object 类,而 Object 类中写有equals()方法。编程人员可以通过重写 equals() 方法来实现自己的比较策略,也可以不重写,使用Object类的equals()比较策略。

//Object类中的equals()方法源码
public boolean equals(Object obj) {return (this == obj);
}

从 Object 类的 equals() 源码可以看到,如果编程人员没有显示地重写 equals() 方法,则默认比较两个引用是否指向同一个对象。

补充: 关于基本数据类型包装类的比较

由于 Java 中万物皆对象,就连基本数据类型也有其对应的包装类,那么它们对应的比较策略是什么呢?

public static void main(String[] args) {int a = 3;Integer b = new Integer(3);System.out.println(b.equals(a));    //true, 自动装箱
}

从上面的代码可以看到尽管两个引用不同, 但是输出的结果仍为 true, 证明 Integer 包装类重写了 equals() 方法,追踪其源码:

//Integer类中的equals方法
public boolean equals(Object obj) {if (obj instanceof Integer) {return value == ((Integer)obj).intValue();}return false;
}

从源码看到,基本类型包装类在重写equals()后,比较的还是基本数据类型的值。

结束

通过探索 == 和 equals() 的区别,我们摸清楚了二者别后的比较策略,同时也对 Java 中 equals() 方法的设计进行了思考,相信大家在今后的 Java 编程实战中不会再为相等判断而烦恼了。

部分面试资料链接:https://pan.baidu.com/s/1qDb2YoCopCHoQXH15jiLhA

密码:jsam

想获得全部面试必看资料,关注公众号,大家可以在公众号后台回复“知乎”即可。

617a3a64402cec13f4dce4d2ddd19d5d.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/507214.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据通信原理_同网段主机通信原理

本篇文章介绍数据通信中最基础,最关键的原理之一,两台通网段的主机如何通信。获得更多技术资料和免费学习视频,加入讨论群:752160765适合两台普通电脑之间,两台服务器之间,两台手机之间,电脑和打…

java jdk 未知错误_解决JAVA JDK安装出错的最常见问题,帮你排除困扰

一般来说,安装JAVA JDK的整个流程是很简单的,只要按照提示进行操作即可,就不会出现问题。但是呢,有小伙伴反映说,之前安装了JAVA JDK,进行卸载重装的时候出现错误提示,“正在进行另一Java安装”…

定义const变量是不可以赋值_JavaScript的声明方法和作用范围,常见的结构赋值类型和使用场景...

链接:https://juejin.im/post/5d9bf530518825427b27639d声明const命令:声明常量 let命令:声明变量作用作用域全局作用域函数作用域:function() {}块级作用域:{}作用范围var 命令在全局代码中执行const命令和let命令只能…

java社区活跃度_Java并发编程-活跃度问题

在讲问题前,我先说明一下什么是活跃度?一个并发应用及时执行的能力称作活跃度。我主要讲死锁问题,顺带介绍一下饥饿,弱响应性和活锁。死锁死锁这个词大家都听过,我先来罗列一下产生死锁的四个必要条件:(1) …

java8 di_java8 多个list对象用lambda求差集操作

业务场景:调用同步接口获取当前全部有效账户,数据库已存在部分账户信息,因此需要筛选同步接口中已存在本地的帐户。调用接口获取的数据集合List list response.getData().getItems();本地查询出来的账户集合List towList accountRepository…

怎么抓python程序的包_如何在AWS上部署python应用程序

如何在AWS上部署python应用程序,学姐呕心沥血亲自总结,亲测有效,比网上看网上大把大把的文档要快得多!作者:蕾学姐亚马逊云计算服务(Amazon Web Services,缩写为AWS),由亚…

【Hadoop】Zookeeper架构/特点

Zookeeper 中的角色主要有以下三类: Zookeeper需要保证高可用性和强一致性为了支持更多的客户端,需要增加更多Server,但是Server增多,意味着投票阶段延迟增大,会影响整个系统的性能。所以在3.3.0中ZK引入的新角色&…

wpf 按钮样式_键盘 | 01.在程序集间引用样式

设置Button和TextBox的特定颜色和字体的样式和默认样式,并在程序集间引用。从零开始用WPF/C#开发一个键盘指示器项目完整开源、免费,不依赖第三方库编译好的先行版程序在微信公众号(香辣恐龙蛋)下载。文章同时发布在微信公众号(香辣恐龙蛋)、B站(香辣恐龙…

怎么去除表中的系统导出的字符_EXCEL非常有用的字符函数LEN、LENB,财务工作者的必备利器...

LEN函数与LENB函数是比较常用的函数,在实际中应用那是相当广的,尤其在财务工作中的使用频率是相当的高。我就一起看看实际工作中哪些地方用到了它。我们先简单说下它的用法,很简单,LEN(text)、LENB(text),两个用法是一…

java软尾山地车碳_JAVA FURIA 27.5入门软尾山地车评测

铝合金车架、前后100mm避震行程、超短把立、长款燕把、27.5轮径……之前跟大家讲过,在这台车上你能拥有全避震车型所应该具备的所有基础元素。2个月的时间已经过去,这台车到底怎么样呢?我们一起来看一下。优点:质量靠谱&#xff0…

java 模拟路由表_Router的路由表

Router中使用routers字段表示路由表,这是一个数组,每个元组的类型是[desnination,nexthop],其中destination表示目的网段(cidr),nexthop表示下一跳的IP,举例如下:“routes”:[ { “destination”:”10.50.10.0/24” “…

无符号有符号乘法_刘帅嵌入式系统-乘法指令

ARM有两类乘法指令:一类为32位的乘法指令,即乘法操作的结果为32位;另一类为64位的乘法指令,即乘法操作的结果为64位。两类指令共有以下6条。MUL:32位乘法指令MLA:32位带加数的乘法指令SMULL:64位…

php导出csv_原生PHP实现导出csv格式Excel文件的方法示例【附源码下载】

本文实例讲述了原生PHP实现导出csv格式Excel文件的方法。分享给大家供大家参考,具体如下:效果图源码分析index.phprequire_once "./Export.php";//测试数据$headerList [列名1,列名2,列名3];$data [[值1,值2,值3],[值11,值22,值33],[值111,值…

python 颜色_如何使用python中matplotlib库分析图像颜色

用代码分析图像可能很困难。你如何使代码“理解”图像的上下文?通常,使用AI分析图像的第一步 是找到主要颜色。在如何使用python中matplotlib库分析图像颜色中,我们将使用matplotlib的 image类在图像中找到主色 。查找主导色也是你可以使用第三方API进行…

cnn 准确率无法提升_清华类脑芯片再登Nature: 全球首款基于忆阻器的CNN存算一体芯片...

传统计算架构中计算与存储在不同电路单元中完成,造成大量数据搬运功耗增加和额外延迟,被认为是冯诺依曼计算架构的核心瓶颈。人类的大脑却并非如此,而是直接在记忆体里计算。被认为具有「存算一体」潜力的忆阻器,因而成为类脑计算…

oracle 几个字段中某个字段大于0其他字段不再进行统计?_如何深入理解MySQL 8.0直方图?...

MySQL8.0 新功能直方图,继承于Oracle ,MairaDB的实现方式。 那下面从mysql角度认识下,直方图是什么。先看下官方直方图的实现方式。 从上图上可以看到原来是ANALYZE命令。先了解一下MySQL里 ANALYZE命令到底有什么用。ANALYZE在MySQL里提交一…

godaddy修改php版本,Godaddy美国主机Plesk面板修改PHP版本教程

由于不同的需求,我们站长朋友们建站所用的网站程序也不尽相同,有PHP、ASP和ASP.NET等。Godaddy美国主机作为全球最大域名主机商,当之无愧成为站长使用最多的主机。不少朋友应该都知道不同的网站程序对于PHP和ASP的版本要求又不一样&#xff0…

mysql数据结构_mysql的底层数据结构

一.数据结构1. 二叉树特点:左侧子节点比父节点小,右侧子节点比父节点大(对于同一个父节点下的两个子节点)缺点:对于一直递增得数据不能存在该数据结构中,会变成链表,不能降低树的高度图 1-1图1-22. 红黑树特…

winform判断线程有没有完成_并发编程系列1:线程池的架构实现、大小配置、及四种线程池使用...

△ 公众号回复关键词“架构” 即可领取《1500BAT架构及面试专题合集》本篇为线程池系列文章之一,不经常使用线程池的童鞋,还有对几种线程的使用不甚了解的童鞋,可以读一下此文,并关注后续线程池相关文章连载。 本篇内容大纲&#…

python枚举是什么意思,什么是枚举python

枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期、月份、状态等。Python 的原生类型(Built-in types)里并没有专门的枚举类型,但是我们可以通过很多方法来实现它,例如字典、类等&#x…