主要内容:等价关系,利用AF定义不可变类型的等价性,==与equals(),可变类型的等价性
不可变类型的等价性
判定方法:AF(映射到相同的结果即等价)、集合(少用、理论上的)、观察者(对两个对象调用任何相同的操作都会得到相同的结果)
考察重点:例:
1.当观察者与AF定义的等价性相同时,观察者用哪些方法是正确的?
(1)只有size :只能保证集合中元素个数相等,不能保证元素相等
(2)只有contains: 能确保通过反复使用确保集合中的元素
(3)有size和contains: 能
(4)有length和contains: length可能会使本来相等的变成不等价的
2.当观察者与AF定义的等价性相同时,观察者用哪些方法与AF一致?
(1)size:同(2)contains:同(3)union:同
(4)length:集合同原来的string不一定同
(5)isAllLowercase:大小写不一致但含元素相同的
(6)first:首字母大小写不同的
==与equals()
==是引用等价性,判断内存空间的地址是否相等
equals()是对象等价性,比较操作内容
基本数据类型不支持equal,用==判断相等
对象类型的equal如果不重写则继承至Object的equals,也是==
对于自己设计的ADT,根据需求自己重写equals
重写equals的契约
约定:符合自反传递对称的等价关系,对象不被修改则调用结果永远一致、x.equals(null)返回false、等价的对象的hashCode结果一致、对类的所有对象都生效
为不打破hash表的RI,要求等价对象必须有相同的hashCode,重写equals也必须重写hashCode(除非能保证ADT不会被放入到hash类型的集合类中)
简单方法:仅返回少量常量值,简便但会使性能受到极大影响
方法:为用于确定相等性的对象的每个组件计算一个哈希代码(通常通过调用每个组件的hashCode方法),然后将它们结合起来,加入一些算术运算。
可变类型的等价性
观察等价性:在不改变状态的情况下,两个对象看起来是否一致(Java中大多数可变类型,如集合类),可能会导致bug
行为等价性:调用对象的任何方法都展现出一致的结果(其他可变类,如StringBuild)
如果mutable类型的对象包含在Set集合类中,发生改变后集合类的行为将不确定,因此对可变类型实现行为\引用等价性,即使其内存地址相等,无需重写equals和hashCode,直接继承即可。判断期内元素的相等性可以定义其他名字的方法。只有这样,才能确保一致性、避免破坏哈希表的RI、避免别名引用带来的bug。
一些例子中的考点