【第7条】在改写equals的时候请遵守通用约定

2024-04-17 22:48

本文主要是介绍【第7条】在改写equals的时候请遵守通用约定,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《第3章 对所有对象都通用的方法》


    这是我认为最有用的一章,真的该好好问问自己,这些最最基础的东西,自己都掌握吗?
    Object是个即普通又特殊的类。说它普通是因为所有的类都是由它派生来的,说它特殊是因为它是所有其他类的父类必须先了解它才能写好你自己的类。
    Object所有的非final方法,都是为改写(override)而设计的,改写方法都有明确的约定,这一章就是讲述该如何改写这些法方的。

 

【第7条】在改写equals的时候请遵守通用约定

    equals即“相等”之意,看起来改写很容易,但是实际中却容易犯错误。
equals的改写规范:
 1)自反性:x.equals(x)一定为true
 2)对称性:当且仅当x.dquals(y)为true;那么y.equals(x)也必须为true
 3)传递性:如果x.equals(y)为true,y.equals(z);那么x.equals(x)也必须为true
 4)一致性:对于任意引用值x和y,如果用于equals比较的对象信息没有被修改的话,那么多次调用x.dquals(y)返回的值是一致的
 5)对于非空引用值x,x.equals(null)一定返回false
 
    看上去这些约定都是废话,一个头脑没有问题的人,对于“相等”的理解,不会对以上五条产生任何疑问。但落实到代码上就不是这么简单了,在改写完equals方法后用一些测试代码来逐条对照检查一下是非常有必要的。
   

    一旦违反了其中一条,后果就是不堪设想的。


    比如:自反性。如果违反了“x.equals(x)一定为true”这一条。当这样的类的一个实例被放入到一个集合(collection)中后,当你通过contains方法向集合询问是否含有此实例时,集合会告诉你“没有”。为什么呢?contains方法就是靠调用放入其中的对象的equals方法来判断是包含的(编写contains方法的人认为所有的类都该有一个满足约定的equals方法)。
   
写好equals方法的“处方”:
 1)使用==操作符检查“实参是否为指向对象的一个引用”
     if (o==this)
       return true;


 2)使用instanceof操作符检查“实参是否为正确的类型”
     if (!(o instanceof MyClass))
       return false;


 3)把实参转为正确的类型
     MyClass mo = (MyClass)o;


 4)对于该类中每一个“关键(significant)”域,检查实参中的域与当前对象中对应的域值是否匹配
     if (!(this.field == null ? o.field == null : this.equals(o.field)))
     //或者写成 if(!(this.field == o.field || (this.field != null && this.field.equals(o.field)))) 对于this.field和o.field通常是相同的对象引用,会更快一些。
       return false;
     //比较下一个field
     //都比较完了
     return true;


 5)最后还要确认以下事情
   5.1)改写equals的同时,总是(必须)要改写hashCode方法(见【第8条】),这是极容易被忽略的,有极为重要的
   5.2)不要企图让equals方法过于聪明
   5.3)不要使用不可靠的资源。如依赖网络连接
   5.4)不要将equals声明中的Object对象替换为其他类型。
         public boolean equals(MyClass) 这样的声明并不鲜见,往外使程序员数小时搞不清楚为什么不能正常工作
         原因是这里是重载(overload)而并不是改写(override)(或称为覆盖、重写)
         相当于给equals又增加了一个实参类型为MyClass的重载,而实参为Object的那个equals并没有被改写,依然还是从Object继承来的最初的那个equals,所总是看不到程序员想要的效果。因为类库或其他人写的代码都是调用实参为Object型的那个equals方法的(别人又如何在事前知晓你今天写的MyClass呢?)

 

 

 

【Effective Java 学习笔记】系列连载专题请见:
http://tonylian.iteye.com/categories/64208

 

这篇关于【第7条】在改写equals的时候请遵守通用约定的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/913076

相关文章

j2EE通用jar包的作用

原文:http://blog.sina.com.cn/s/blog_610901710101kx37.html IKIKAnalyzer3.2.8.jar // 分词器 ant-junit4.jar // ant junit antlr-2.7.6.jar // 没有此包,hibernate不会执行hql语句。并且会报NoClassDefFoundError: antlr

Win32函数调用约定(Calling Convention)

平常我们在C#中使用DllImportAttribute引入函数时,不指明函数调用约定(CallingConvention)这个参数,也可以正常调用。如FindWindow函数 [DllImport("user32.dll", EntryPoint="FindWindow", SetLastError = true)]public static extern IntPtr FindWindow

通用内存快照裁剪压缩库Tailor介绍及源码分析(一)

背景 我们知道内存快照是治理 OOM 问题及其他类型的内存问题的重要数据源,内存快照中保存了进程虚拟机的完整的堆内存数据,很多时候也是调查其他类型异常的重要参考。但是dump出来的堆转储文件.hprof往往很大,以 LargeHeap 应用为例,其 OOM 时的内存快照大小通常在512M左右,要有效的存储和获取都是一个问题。 线下拿到hprof文件相对容易,也可以预防OOM,但覆盖的场景十分有

SpringBoot中利用EasyExcel+aop实现一个通用Excel导出功能

一、结果展示 主要功能:可以根据前端传递的参数,导出指定列、指定行 1.1 案例一 前端页面 传递参数 {"excelName": "导出用户信息1725738666946","sheetName": "导出用户信息","fieldList": [{"fieldName": "userId","fieldDesc": "用户id"},{"fieldName": "age","fieldDe

html记账本改写:数据重新布局,更好用了,没有localStorage保存版本

<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><title>htm记账本</title><style>table {user-select: none;/* width: 100%; */border-collapse: collapse;}table,th,td {border: 1px solid bla

数据结构(邓俊辉)学习笔记】排序 5——选取:通用算法

文章目录 1. 尝试2. quickSelect3.linearSelect:算法4. linearSelect:性能分析5. linearSelect:性能分析B6. linearSelect:性能分析C 1. 尝试 在讨论过众数以及特殊情况下中位数的计算方法以后,接下来针对一般性的选取问题,介绍优化的通用算法。 既然选取问题的查找目标就是在整个数据集中按大小次序秩为 k

c++通用模板类(template class)定义实现详细介绍

有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同,如下面语句声明了一个类:class Compare_int { public : Compare(int a,int b) { x=a; y=b; } int max( ) { return (x>y)?x:y; } int min( ) { return (x&... 有时,有两个或多个类,其功能是相同的,仅仅是数

5款ai智能改写工具,自动改写文章效率惊人

在这个信息迭代加速的时代,ai智能改写工具犹如一把魔法钥匙,轻轻一转,便能开启文章改写的大门。想象一下,那些曾经费尽心思打磨的文章,如今只需几秒钟,就能以全新的面貌示人,这不仅是一场效率的革命,更是创作者灵感迸发的源泉。下面,让我们一起探索这5款ai智能改写工具,让高质量的文章改写不再成为难题。   1、火呱ai写作   它是一款强大的ai写作工具,不仅能够对文章进行改写,而且还能根据

NXP,S32K1XX汽车通用微控制器开发笔记

文章目录 1. 概述2. 开发环境配置2.1 S32 Design Studio2.2 安装SDK2.3 新建demo工程2.4 字体配置2.5 按需求修改demo2.5.1 修改pin脚定义2.5.2 增加串口打印功能 2.6 编译代码2.7 debuger 配置 参考 1. 概述 S32K1系列32位微控制器(MCU)提供基于Arm® Cortex®-M的MCU,以及基

使用Mybatis SqlProvider类相关注解生成通用Mapper接口

使用Mybatis SqlProvider类相关注解生成通用Mapper接口 1. 使用Mybatis @SelectProvider @InsertProvider @UpdateProvider @DeleteProvider注解封装BaseMapper<E, I>通用接口, 普通实体类Mapper接口只需要继承该接口, 即可实现基础常用的CRUD功能. BaseMapper<E, I>