软件构造课程阶段总结(七):ADT和OOP中的等价性

等价关系(Equivalence Relation)

现实中每个对象都是独特的,并不存在完全相等,但存在对“等价性”的需要。

数学中完全相等存在

等价关系问题即为在软件领域中界定判断为相等:等价、可相互替代的

数学中认为等价关系为“自反、对称、传递”的关系。

判断等价的三种方法

ADT中等价:抽象函数AF

在ADT中,抽象函数AF映射到同样的结果(AF(a)==AF(b))=两对象等价.

外部观察者角度:

对两个对象执行任何相同操作,得出的结果都相同,则认为两对象等价。(为充要关系)

==和.equals()

Java下有==和.equals()两种操作来测试相等性,其有不同原理和用法。

==是引用等价性

其为真当且仅当两个引用指向内存中相同位置(快照图中箭头指向同一个气泡)

.equals()是对象等价性

按照这一方法的内部程序比较对象的内容。自定义ADT时需要重写Object的.equals()方法(其初始使用==判断),即在创建一个新数据类型时也需要给出两个该对象相等的判断条件。重写最好写出@Override,并确保签名匹配,复制Spec

instanceof

该操作符测试对象是否为特定类型的实例,属于动态类型检查,最好不要用在除equals之外。建议用多态取代instanceof

对象的契约

equals()的契约

当重写equals()方法时,必须遵守其契约:

满足自反、传递、对称的等价关系

除非对象被修改了,否则调用多次equals()应同样的结果

“相等”的对象,其hashCode()的结果必须一致

对于任何非空引用值x,x.equals(null)必须返回false。

equals是一个在所有对象上的全局等价关系,用“是否为等价关系”检验你的equals()是否正确。

hashcode()的契约

每当在应用程序执行过程中对同一对象进行多次调用时,hashCode方法必须一致地返回相同的整数,只要不修改在该对象的平等比较中使用的信息。

如果两个对象根据 equals(Object) 方法相等,那么对这两个对象分别调用hashCode()方法必须产生相同的整数结果。

等价的对象必须有相同的hashCode。

不相等的对象,也可以映射为同样的hashCode,但性能会变差。

相等的对象必须有相等的哈希代码

如果重写equals(),必须也重写hashCode()

不相等的对象应该有不同的哈希代码

在构造它时考虑到所有的值字段

除非对象突变,哈希代码必须不改变

可变类型的等价性

分为观察等价性和行为等价性

  • 观察等价性:在不改变状态的情况下,两个可变对象是否看起来一致
  • 行为等价性:调用对象的任何方法都展示出一致的结果

注意:对于不可变对象,观察性和行为性相等是相同的,因为没有任何mutator方法。

对可变类型来说,往往倾向于实现严格的观察等价性。

Java对其大多数可变数据类型(如集合)使用观察性相等,但其他可变数据类(如StringBuilder)使用行为相等。

如果两个不同的List对象包含相同的元素序列,则equals() 表示它们相等。

但在有些时候,观察等价性可能导致bug,甚至可能破坏RI

在JDK中,不同的mutable类使用不同的等价性标准:

观察等价性

  • Date类的equals()
  • List类的equals()

行为等价性

StringBuilder类的equals()

对可变类型,实现行为等价性即可。也就是说,只有指向同样内存空间的objects,才是相等的。所以对可变类型来说,无需重写这两个函数,直接继承Object的两个方法即可。

如果一定要判断两个可变对象看起来是否一致,最好定义一个新的方法。

总结:

  • 不可变类型:重写equals()和 hashCode()
  • 可变类型:不该重写equals()和 hashCode()

自动包装和等价性

原始类型及其对象类型的等价物,例如,int和Integer。

如果创建两个具有相同值的Integer对象,它们将满足equals() ,但是不满足==。

但是强制转换为int后,就可以满足==。

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值