`
TonyLian
  • 浏览: 401522 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【第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

 

分享到:
评论

相关推荐

    winform 重写Equals源码

    在某些情况下,尤其是自定义控件或者业务实体类的设计中,我们可能需要重写`Equals`方法来实现特定的比较逻辑。下面我们将深入探讨WinForm中重写`Equals`方法的相关知识点。 首先,`Equals`方法是`Object`类中的一...

    Java中equals()与hashCode()的原理与设计

     2、为什么改写equals()的时候,总是要改写hashCode()  两个原则:  hashCode()的返回值和equals()的关系如下:  如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。  如果x.equals(y)返回...

    重写equals方法

    什么时候需要重写 equals 方法? ------------------------- 第一种情况:如果类中提供的 equals 方法无法满足需求,则需要重写 equals 方法。例如,在 String 类中,equals 方法用于比较两个字符串的内容是否相同...

    java中equals和==的区别

    在第一个程序中,s1 先被放到了池中,所以在 s2 被创建的时候,程序找到了具有相同值的 s1,将 s2 引用 s1 所引用的对象。 在第二个程序中,我们使用了 new 操作符,它明白的告诉程序:"我要一个新的!不要旧的!...

    java中equals()函数的用法 equals和==的区别

    在Java编程语言中,`equals()`方法和`==`运算符是两个经常被用来比较对象是否相等的关键概念。理解它们的区别对于编写出正确、健壮的代码至关重要。 首先,`==`运算符用于基本类型(如int, char, boolean)的比较,...

    java_equals用法

    java_equals用法,用来熟悉重写equals方法的

    Java容器集合(equals 和 hashCode+基础数据结构+ArrayList+Vector和LinkedList)

    重写equals方法需要遵守通用约定,hashCode方法的实现需要保证equals相同的两个对象的hashCode结果一致。ArrayList、Vector和LinkedList是Java中三种常见的容器集合,每种集合都有其特点和应用场景。

    hashcode和equals方法

    equals()和hashcode()这两个方法都是从object类中继承过来的。当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法.

    Java语言深入_equals

    5. `o.equals(null)`任何时候都应返回`false`。 `Object`类提供了`equals`方法的默认实现,它仅比较对象的引用,也就是说,只有当两个对象是同一个实例时,`equals`才返回`true`。这对于值比较是没有意义的,因此在...

    重载equals方法示例

    重载equals方法示例重载equals方法示例重载equals方法示例重载equals方法示例重载equals方法示例

    equals问题经典

    在Java编程语言中,`equals()`方法是用来比较两个对象的内容是否相等的,而`==`操作符则是用来比较两个变量是否引用同一个对象。这里我们将深入探讨`equals()`方法的用法,以及它与`==`的区别,同时解决题目中提出的...

    重写toString和equals方法

    Java 对象的toString和equals方法重写 在 Java 中,每个对象都继承自 Object 类,而 Object 类中定义了两个重要的方法:toString() 和 equals()。这两个方法都是非常重要的,它们分别用于对象的字符串表示和对象...

    Java中equals方法隐藏的陷阱

    - **类型参数错误**:有时候开发者可能会将方法签名修改为`public boolean equals(MyClass other)`这样的形式。虽然这看起来更直观,但实际上会导致类型转换异常,当尝试比较不同类型但继承自同一父类的对象时尤其...

    重写equals和hashcode方法_equals_重写equals和hashcode方法_

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是Object类中的两个核心方法,所有类都默认继承自Object类。这两个方法在处理对象比较和集合操作时起着至关重要的作用。当我们创建自定义类并需要对对象进行精确...

    java 资料 equals 与== 的区别

    Java 中的equals和==的区别 Java 是一种面向对象的编程语言,其中有两种数据类型:基本数据类型和引用数据类型。基本数据类型包括整数类型、浮点数类型、字符类型、布尔类型等,共有八种;而引用数据类型则包括 ...

    equals与hashCode在实际开发中的重写写法

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是两个非常重要的成员,尤其是在处理对象比较和集合操作时。这两个方法通常与`Object`类中的默认实现相关联,但为了在实际开发中实现正确的对象比较和哈希表操作...

    知识点 比较运算符==和equals方法的比较

    在Java编程语言中,比较运算符`==`和`equals()`方法是用来检查两个对象是否相等的,但它们之间存在显著的区别。理解这些差异对于编写正确的代码至关重要。 首先,我们来看`==`运算符。它主要用于基本数据类型的比较...

    ==和equals的区别

    在 Java 中,比较值大小有两种方法:== 和 equals,这两个方法的使用场景和比较规则不同,下面我们将详细探讨它们的区别。 基本数据类型和引用数据类型 在 Java 中,有两种数据类型:基本数据类型和引用数据类型。...

    equals方法的重写.docx

    ### equals方法重写知识点解析 #### 一、equals方法简介 `equals`方法是Java语言中Object类的一个重要成员方法,其默认实现是比较两个对象的内存地址是否相同(即是否为同一个对象)。为了使对象之间能够基于内容...

    Java中的==和equals区别

    在Java编程中,比较对象的相等性是一个常见的需求,但很多初学者对于`==`运算符与`equals`方法的区别容易混淆。本文将深入探讨两者之间的差异,以及它们在不同场景下的应用。 #### `==` 运算符 `==`运算符主要用于...

Global site tag (gtag.js) - Google Analytics