java继承中的 equals + hashCode+toString

【0】README

0.1)本文转自 core java volume 1, 旨在理清 equals + hashCode方法;
0.2) 特别说明: 在java中, 只有基本类型不是对象, 例如,数值, 字符和布尔类型的值都不是对象; 但是所有的数组类型,不管是对象数组还是基本类型的数组都扩展于Object类;
0.3) 最后,我们还补充了对 toString 方法的描述;


【1】equals方法

1.1) Object中的 equals 方法用于检测一个对象是否等于另外一个对象;(在Object类中, 这个方法比较的是内存地址, 判断的是两个对象是否具有相同引用)
1.2)看个荔枝:
这里写图片描述
Hint)

  • H1)为了防备name 或 hireDay 可能为null的情况: 需要使用 Objects.equals 方法;如果两个参数都为 null, Objects.equals(a, b) 返回 true; 如果其中一个为null, 则返回 false; 否则,两个参数都不为null, 则调用 a.equals(b);(注意是Objects not Object)
  • H2)利用这个方法, Employee.equals 方法的最后一条语句要改写为:
return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);

1.3)在子类中定义 equals 方法时, 首先调用超类的 equals; 如果检测失败,对象就不可能相等, 如果超类中的域都相等, 就需要比较子类中的实例域;
这里写图片描述
1.4)java语言规范要求 equals 具有以下特性:

  • 自反性:非空引用 x,x.equals(x) 应该返回true;
  • 对称性:非空引用x 和 y, x.equals(y) 返回ture, 那么 y.equals(x) 也应该返回ture;
  • 传递性:对于 非空引用x 、y 和 z, x.equals(y) 返回ture, 那么 y.equals(z) 也应该返回ture, 则 x.equals(z) 也应该返回 true;
  • 一致性:如果x 和 y 引用的对象没有发生变化, 反复调用 x.equals(y) 应该返回同样的结果;
  • 对于任意非空应用x, x.equals(null) 应该返回false;

1.5)出现的问题+解决方法

  • 当子类和父类对象分别作为equals 的隐式参数,导致不满足对称性的情况: e.equals(m), 这里的e是一个 Employee对象,m是一个 Manager对象,并且两个对象具有相同的属性值;如果在 Employee.equals中用 instanceof 检测,就会返回 true, 然而这意味着反过来调用: m.equals(e) 也需要返回true; 对称性不允许这个方法调用返回 false, 或者抛出异常;猛然间,让人感觉到 instanceof 并不是那么完美;
  • 下面从两个截然不同的情况看一下这个问题:
    • 1)如果子类能够拥有自己的相等概念, 则对称性需要将强制采用getClass 进行检测;
    • 2)如果由超类决定相等的概念, 那么就可以使用 instanceof 进行检测, 这样可以在不同子类的对象间进行相等的比较;

【2】下面给出编写一个完美的 equals 方法的建议:

  • 2.1)显式参数命名为 otherObject, 稍后需要将它转换为另一个叫做 other的变量;
  • 2.2)检测this 与 otherObject 是否引用同一个对象:
    if(this == otherObject) return true; 实际上, 这是一种经常采用的形式, 因为计算这个等式要比一个一个地比较类中的域所付出的代价小得多;
  • 2.3)检测otherObject 是否为 null, 如果为 null ,则返回 false, 这项检测很有必要:
    if(otherObject == null) return false;
  • 2.4)比较this 与 otherObject 是否属于同一个类: 如果equals 的语义在每个子类中有所改变,就是用 getClass 进行检测:if(getClass() != otherObject.getClass()) return false;
  • 2.5) 将 otherObject 转换为 相应的类类型变量:
    ClassName other = (ClassName)otherObject;
  • 2.6)现在开始对所有需要比较的域进行比较了:
    使用 == 比较基本类型域, 使用 equals比较对象域, 如果所有的域都匹配返回 true, 否则返回 false;
    return field1 == other.field1 && Objects.equals(field2, other.field2) && ……;
    如果在子类中重新定义 equals, 就要在其中包含 调用 super.equals(other);

Hint)对于数组类型的域, 可以使用静态的Arrays.equals 方法检测相应的 数组元素是否相等;
Alert)看个荔枝(下面是实现 equals 方法的一种常见的错误):
这里写图片描述
代码分析(Analysis):

  • A1)这个方法声明的显式参数类型是 Employee, 其结果并没有 覆盖 Object类的 equals 方法,而是定义了一个完全无关的方法;
  • A2)为了避免发生类型错误, 可以使用 @Override 对覆盖超类的方法进行标记;
@Override
public boolean equals(Object other)
  • A3)如果出现了错误,并且正在定义一个新方法,编译器就会给出 错误报告;如, 假设将下面的声明添加到 Employee类中, 就会看到一个错误报告, 这是因为这个方法并没有覆盖超类Object 中的 任何方法:
@Override 
public boolean equals(Employee other)

【3】hashCode 方法

3.1)定义:散列码是由对象导出的一个整型值, 散列码没有规律的;如,x和y 是两个不同的对象, x.hashCode() 和 y.hashCode() 基本上不会相同的;
3.2)String 类的 hashCode 散列码:

  • 3.2.1)String类通过下列算法计算散列码:
int hash = 0;
for(int i=0;i<length(); i++)hash = 31 * hash + charAt(i);
  • 3.2.2) hashCode方法定义在了 Object类, 因此每个对象都有一个默认的散列码, 其值为对象的存储地址:
    这里写图片描述
    对以上打印结果的分析(Analysis):

    • A1)字符串s 和 t 拥有相同的散列码, 这是因为字符串的散列码是由内容导出的, 而字符串缓冲sb 和 tb 却有着不同的散列码,这是因为 在StringBuffer 类中没有定义hashCode 方法,它的散列码是有 Object类的默认 hashCode 方法,以便用户可以 将对象插入到散列表中;
    • A2) hashCode方法应该返回一个整型数值,并合理的组合实例域的散列码, 以便能够让各个不同的对象产生的散列码更加均匀;

3.3)看个荔枝, 下面是 Employee类 的 hashCode方法:
这里写图片描述
3.4)还可以在java7中做两个改进(improvement):

  • I1) 最好使用 null 安全 的方法 Objects.hashCode , 如果参数为null, 这个方法会返回0, 否则返回对参数调用 hashCode的结果;
  • I2)还有一个方法: 需要组合多个散列值, 可以调用 Objects.hash 并提供多个参数,这个方法会对各个参数调用 Objects.hashCode, 并组合这些散列值; 如 Employee.hashCode 的方法可以简写为:
public int hashCode()
{return Objects.hash(name, salary, hireDay);
}

Attention)

  • A1) equals 方法与 hashCode 的定义必须一致, 如果x.equals(y) 返回 true, 那么 x.hashCode() 就必须与 y.hashCode() 具有相同的值;
  • A2) 如, 如果用定义的Employee.equals 比较雇员的Id, 那么 hashCode就需要散列Id, 而不是 雇员的 姓名或存储地址;

Hint)如果存在数组类型的域, 那么可以使用静态的 Arrays.hashCode 方法计算一个散列码, 这个散列码由数组元素的散列码组成;


【4】toString方法

4.1)随处可见toString 方法的原因是: 只要对象与一个字符串通过操作符 + 连接起来,java编译器就会自动地调用 toString 方法, 以便获得这个对象的字符串描述;
Hint)在调用它 x.toString()的地方可以用 “”+x替代, 这条语句将一个空串与 x 的字符串表示相连接, 这里的x就是 x.toString();
4.2)Object定义了toString()方法,用来打印输出对象所属的类名和散列码;如,

System.out.println(System.out) 

这里写图片描述
Warning)

  • W1)数组继承了 Object类的 toString方法, 数组类型将按照旧格式打印;
  • W2)修正的方式是调用静态方法 Arrays.toString
    这里写图片描述
  • W3)要想打印多维数组, 需要调用 Arrays.deepToString 方法;

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

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

相关文章

纹理和基元_自定义基元和DTO的(反)序列化和验证

纹理和基元最近&#xff0c;我们为您提供了新的HTTP框架HttpMate。 在介绍性文章中 &#xff0c;我们将请求和响应映射到域对象称为“最复杂的技术细节”&#xff0c;以及如何通过另一个伴侣MapMate帮助我们。 实际上&#xff0c;当将请求属性映射到您的域对象时&#xff0c;M…

vim 常用命令

文章目录普通命令模式下技巧汇总切换到插入模式切换到可视模式切换至底行命令模式复制内容复制命令的记忆技巧粘贴/恢复修改/改写删除/剪切字符大小写切换选择文本游标移动剪切文本/移动文本滚屏/翻页撤回查看文档状态查找/搜索字符串查看历史命令查看历史搜索记录多窗口操作保…

常见花材的固定的方法有哪些_旋流器常见的故障及处理方法有哪些?

旋流器除了用在磨矿循环中的分级作业外&#xff0c;还可以用于脱泥、脱水以及脱除浮选药剂等。此外&#xff0c;还可以用做重悬浮液选矿&#xff0c;其分选粒度可达0.1毫米左右。旋流器有许多优点&#xff0c;构造简单&#xff0c;没有运动部件&#xff0c;单位容积的处理能力大…

二叉堆(优先队列)

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c;但源代码均为原创&#xff1b;旨在理清二叉堆&#xff08;优先队列&#xff09; 堆的其他操作及其应用&#xff0c; 以便让朋友些知道为什么要学习优先队列&#xff1b; 【1】二叉堆 1.0&#xff09;…

java自定义外部接口_如何使用可外部化的接口在Java中自定义序列化

java自定义外部接口在上一篇文章“用示例介绍的有关Java序列化的一切”中 &#xff0c;我解释了如何使用以下方法序列化/反序列化一个对象 Serializable接口&#xff0c;还说明了如何使用writeObject和readObject方法自定义序列化过程。 Java序列化过程的缺点 但是这些自定义…

python训练营朋友圈留言_用Python发一个高逼格的朋友圈【附代码】

今天二胖要给大家介绍一个Python库&#xff1a;PIL(Python Image Library)下面我们用一个实际的例子看看50行python代码可以做什么神奇的事情这是二胖发的一个朋友圈切图前是一张图切图后就是九张图啦成功霸屏除了可以处理规整的正方形图片还可以处理非规则的图片比如下面这张宽…

vim 编辑器的快捷键

文章目录命令终端界面滚屏命令终端页签切换缓存区切换/文件切换分割窗口/打开新窗口切换窗口移动/旋转/移出窗口关闭窗口调整窗口大小底行命令模式下的编辑快捷键vim 很多指令或者快捷键是大小写敏感。命令终端界面滚屏 快捷键说明Fn ←向上滚屏到开始处Fn →向下滚屏到末尾…

关于二叉堆(优先队列)的其他操作及其应用

【0】README 0.1&#xff09;本文总结于 数据结构与算法分析&#xff1b;源代码均为原创&#xff0c; 旨在了解到我们学习了优先队列后&#xff0c;还能干些什么东西出来&#xff0c; 增加学习的interest&#xff1b; 0.2&#xff09;以下列出了 关于二叉堆&#xff08;优先队…

gradle junit5_JUnit 5和Selenium –使用Gradle,JUnit 5和Jupiter Selenium设置项目

gradle junit5Selenium是一组支持浏览器自动化的工具和库&#xff0c;主要用于Web应用程序测试。 Selenium的组件之一是Selenium WebDriver&#xff0c;它提供客户端库&#xff0c;JSON有线协议&#xff08;与浏览器驱动程序进行通信的协议&#xff09;和浏览器驱动程序。 Sele…

ubuntu 两块硬盘挂载不上_win10 轉 Ubuntu

目前用了win10兩三年。發現越來越慢&#xff0c;況且已習慣mac OS&#xff0c;所以想用自己的機子來裝個雙系統Linux&#xff0c;慢慢的將win的東西都轉到Ubuntu上。已清空一個磁盤300G,打算就是在這300G裡裝一個Ubuntu&#xff0c;不知道是否夠用&#xff08;雖然很想裝在三星…

包+类导入+静态导入+类放入包中+包作用域

【0】README 0.1&#xff09;本文转自 core java volume 1&#xff0c; 旨在理清 包和类导入的相关知识&#xff1b; 【1】 包 1.1&#xff09; java 允许使用包将类组织起来&#xff0c;包可以方便组织代码&#xff0c;并将自己的代码与别人提供的代码库分开管理&#xff1b…

selenium自动化测试_使用Selenium自动化测试处理多个浏览器选项卡

selenium自动化测试使用Selenium进行自动化测试一直是将萌芽的自动化测试人员培养为专业人员的生命线。 Selenium是开源的&#xff0c;在全球范围内被广泛采用。 结果&#xff0c;您会得到社区的大力支持。 提供了与Selenium绑定的不同语言的多种框架。 因此&#xff0c;您已经…

qt和c#怎么选_请问目前做windows桌面应用程序,MFC、QT、C#哪个更好?

回答问题之前&#xff0c;先装个逼——没有主导过生命周期三年以上的桌面软件项目的&#xff0c;闭嘴。你连一个桌面软件项目的生命周期都没经历过&#xff0c;你凭什么做技术选型&#xff1f;凭信仰吗&#xff1f;装逼结束&#xff0c;正文开始。首先&#xff0c;非主流技术和…

java 白皮书的关键术语

【0】README 0.1&#xff09; 本文转自 core java volume 1&#xff0c;仅供了解&#xff0c;所谓爱屋及乌嘛&#xff1b; 0.2&#xff09; java的设计者编写了颇有影响力的白皮书&#xff0c;用来解释设计的初衷以及完成的情况&#xff0c;并发布了一个摘要&#xff1b;【1】…

当集合a为空集时a的取值范围_高中数学必修一第一章集合分节练习和章末测试题含答案[1] 2...

高中数学必修1 第一章 集合 分节练习和章末综合测试题含答案1 集合的含义与表示1、下列各组对象能否组成一个集合&#xff1f;(1)接近于0的数的全体&#xff1b; (2)2的近似值的全体&#xff1b; (3)平面上到点O 的距离等于1的点的全体&#xff1b; (4)正三角形的全体&#xff…

spring jpa 流式_从响应式Spring Data存储库流式传输实时更新

spring jpa 流式这篇文章详细介绍了从数据库到对该数据感兴趣的任何其他组件进行流更新的幼稚实现。 更准确地说&#xff0c;如何更改Spring Data R2DBC存储库以向相关订阅者发出事件。 对R2DBC和Spring的一点背景知识将对这篇文章有所帮助。 我以前的著作《 使用 Microsoft S…

弹窗页面交互_UI进阶知识-信息提交类弹窗该如何设计?

原文作者&#xff1a;风筝KK 信息提交类弹窗大家应该都比较熟悉&#xff0c;和其他弹窗的区别在于他有输入、选择等操作&#xff0c;比如我们常见的输入验证码、留言回复、充值转账、任务设置等。看上去设计都比较简单&#xff0c;但是当你验收时就会发现问题&#xff0c;为什么…

selenium并行_如何在不同的浏览器中设置Selenium网格以并行执行

selenium并行到目前为止&#xff0c;Selenium是最常用的Web自动化测试工具。 如此受欢迎的原因之一是Selenium的自动跨浏览器测试功能。 Selenium自动化测试可以帮助您在所有主要浏览器&#xff0c;所有主要操作系统甚至移动设备浏览器上进行测试。 您可以在所有功能测试中获得…

java 发展简史

【0】README 0.1&#xff09; 本文转自 core java volume 1&#xff0c;仅供了解Java 的发展历史&#xff0c;它的前世今生&#xff0c;所谓知己知彼&#xff0c;百战不殆&#xff08;just a joke&#xff09; &#xff1b; 【1】java 发展简史 1.1&#xff09;java的历史要…

axios代理跨域 cli4_跨域本质及解决办法

1、什么是跨域&#xff1f;2、如何解决&#xff1f;跨域是前端所独有的&#xff0c;后端不存在跨域问题。是浏览器的一种安全保护手段&#xff0c;为了防止别人抓取、篡改你的网站数据信息。遵循同源策略、同协议&#xff08;http&#xff09;、同域名、同端口&#xff0c;少一…