本章的目标:
§ Understand the properties of an equivalence relation. 等价关系
§ Understand equality for immutable types defined in terms of the abstraction function and observations. 站在观察者角度,利用AF,定 义不可变对象之间的等价关系
§ Differentiate between reference equality and object equality. 引用等 价性和对象等价性
§ Differentiate between strict observational and behavioral equality for mutable types. 可变数据类型的观察等价性和行为等价性
§ Understand the Object contract and be able to implement equality correctly for mutable and immutable types. 理解Object的契约,正确 实现等价关系判定
1 Equivalence Relation 等价关系
ADT是对数据的抽象,体 现为一组对数据的操作。抽象函数AF:内部表示到抽象表示。基于抽象函数AF定义ADT的等价操作。
(关系等价性):等价关系:自反、对称、传递,
– reflexive: E(t,t) ∀ t∈T 自反 – symmetric: E(t,u) ⇒ E(u,t) 对称 – transitive: E(t,u) ∧ E(u,v) ⇒ E(t,v) 传递。
2 Equality of Immutable Types 不变类型的等价
1) 利用AF定义等价性
AF映射到同样的结果,则等价 用抽象函数定义的关系是等价关系。
2) 用观察方法定义等价性。
站在外部观察者角度:对两个 对象调用任何相同的操作,都 会得到相同的结果,则认为这 两个对象是等价的。 反之亦然。
3 == vs. equals() ==与等价之间的关系。
1) == 指的是 引用等价性,即引用到同一个存储地址空间,称为==
equals() 指的是对象等价性
2)对基本数据类型,使用==判定相等
对对象类型,使用equals()判定等价。 如果用==,是在判断两个对象 身份标识 ID是否相等(指向内存里的同一段空间)
4 Implementing equals() 实现equals()函数
在Object中实现的缺省equals()是在判断引用等价性。这通常 不是程序员所期望的因此,需要重写。
步骤: 进行类型比较 和null值判定。严格来说,在没有 AF的情况下直接在 equals()中判断每 个域的等价性,是 不正确的。
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
5 The Object contract 对象的契约
等价关系:自反、传递、对称.
除非对象被修改了,否则调用多次equals应同样的结果.
“相等”的对象,其hashCode()的 结果必须一致.
这些因素结合在一起确保equals是所有对象 的全局等价关系。用“是否为等价关系”检验你的equals()是否正确。
Hash Tables hashCode
哈希表是映射的一种表示形式:将 键映射到值的抽象数据类型。
哈希表的rep不变量包含一个基本约束,即键位于由其哈希代码确定的槽中。
hashcode的设计使得密钥将均匀地分布在索引上。但有时会发生冲突,两个键放在同一索引中。因此,哈希表不是在索 引中保存单个值,而是实际保存一个键/值对列表,通常称为 哈希桶 。一个键/值对在Java中实现为一个包含两个字段的对象。插入时,将一对添加到由哈希代码确定的数组槽中的列表中。
.等价的对象必须有相同的hashCode。程序员应该知 道,为不相等的对象生成不同的整数结果可能会提高哈希表的性能,不相等的对象, 也可以映射为同样的hashCode,但性能会变差。
如果两个相等的对象具有不同的哈希码,则它们可能被放置在不同的插槽中。如果尝试使用与插入值相同的键来查找值,则查 找可能会失败。
6 Equality of Mutable Types 可变类型的等价
观察等价性:在不改变状态的情况下,两个mutable对象是否看起来一致。
行为等价性:调用对象的任何方法都展示出一致的结果。
. 对可变类型来说,往往倾向于实现严格的观察 等价性。 但在有些时候,观察等价性可能导致bug,甚至可能破坏RI
如果某个mutable的对象包含在Set 集合类中,当其发生改变后,集合类的行为不确定 ,务必小心。
对可变类型,实 现行为等价性即可。只 有指向同样内存空间的objects,才是相等的。对可变类型来说,无需重写这两个函 数,直接继承Object的两个方法即可。如果一定要判断两 个可变对象看起来是否一致,最好定义一个新的方法。
7 Autoboxing and Equality