【软构】对象的等价性


前言

在软件构造中,常常需要判断两个对象是否是等价的。在Java中,由于存在两种数据类型ImmutableMutable,其对于等价的判断也是不相同的。

什么是等价关系呢?等价关系应该满足自反、对称、传递的特性。

有两种定义等价性的角度。
一种是从抽象函数AF的视角,AF映射到同样的结果,则等价;
另一种是站在观察者角度,对两个对象调用任何相同的操作,都会得到相同的结果,则认为这两个对象是等价的。


一、Immutable类型的等价性

在代码中,判断两个对象是否具有等价关系,有两种方式,"==".equals()方法。两者分别实现了不同的判定方式。

1.1"=="表达引用等价性

"=="来判断等价性,实际上考量的是两个对象在内存中的地址空间是否一致,对于Immutable类型的对象来说这又被称为引用等价性。一般情况下,对于基本数据类型的判断如int, long, double等都会使用"=="来判断引用等价性。

如果两个对象是引用等价的,那么这两个对象其实就是一个对象,那么他就会满足所有的等价性。

1.2.equals()表达对象等价性

".equals()"方法来判断等价性,要求就没有"=="那么高了,也就是说,满足等价的定义即可。两个对象不一定要是同一个对象,只要这两个对象在我们所关心的维度是等价的就行了,所以可以看出,用equals()方法来判断对象的等价关系是基于实际情况的可以个性化实现的。一般情况下,对于对象类型的数据都会使用equals()方法来判断等价性。

那么如何基于实际情况个性化实现呢?equals()方法是继承自Object()这一父类的,而在Object()equals()方法是实现引用等价性的,这常常不是程序员们所需要的。于是在写一个继承自Object()父类的ADT时,要对equals()方法进行重写。

1.3重写equals()方法

我们首先要重写equals()方法,一定要保证重写后的equals()方法判断的等价性满足定义以及自反、传递、对称的特性。

但是重写了equals()方法就够吗?其实是不够的,我们还要重写Object()父类中的另一个方法HashCode()方法,这是因为在Object()父类中规定了如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 HashCode() 方法都必须生成相同的整数结果。基于这一原因,我们就必须要重写HashCode()保证equals()判断的等价的两个对象,他们的HashCode也要一致才行。如图。在这里插入图片描述

下面是一个示例。
在这里插入图片描述

二、Mutable类型的等价性

对于Mutable类型的对象,常常提到的是观察等价性和行为等价性。之所以不提引用等价性和对象等价性是因为在Mutable类型的对象中,这两种等价性其实是一样的。

2.1观察等价性

观察等价性是指在不改变状态的情况下,两个mutable对象是否看起来一致。对可变类型来说,往往倾向于实现严格的观察等价性。但在有些时候,观察等价性可能导致bug,甚至可能破坏RI,这是因为过段时间后可能两者就不等价了,因为值可能会发生变化。观察等价性同样通过重写equals()HashCode() 方法来实现。

2.2行为等价性

行为等价性是指调用对象的任何方法都展示出一致的结果。对可变类型,实现行为等价性即可。也就是说,只有指向同样内存空间的objects,才是相等的。所以对可变类型来说,行为等价无需重写equals()HashCode()这两个函数,直接继承Object()的两个方法即可。也就是说,对于行为等价的Mutable类型的对象来说,==equals()是一样的。如果一定要判断两个可变对象看起来是否一致,最好定义一个新的方法。

Mutable类型对象equals()方法示例。
在这里插入图片描述

总结

本文总结了对象的等价关系。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值