软件构造回顾(四)

最近,在我复习的时候对于等价性这个问题掌握的不是很好,尤其是有关于重写equals()方法的时候不能够很好地理解。

等价性

等价这个概念最早是在《离散数学》这门课中接触到的,它有三个要素:
1.自反性: 任意x属于A,则x与自己具有关系R,即xRx;
2.对称性: 任意x,y属于A,如果x与y具有关系R,即xRy,则y与x也具有关系R,即yRx;
3.传递性: 任意x,y,z属于A,如果xRy且yRz,则xRz
这是在那一门课中给出的定义,而在这一门科中,我们也延展了这种定义:AF映射到同样的结果,则等价。这也就是说,如果对两个对象用任何相同的操作,得到的结果如果是相同的话,那么就可以认为这两个对象是等价的。

并且,在这门课中,等价性还有着不同的分类:

==和.equals()

在没有接触到这一门课时候,我们在判断两个变量是否相等的时候只会用到==,但是之后学了这门课,并且了解了各种类型在计算机中的储存原理之后,发现‘==’并不能总是很好的反应等价这个性质。
所以,这门课中引入了.equals()这个方法,==强调的是引用等价性,而.equals()代表了对象等价性,从这两个名字上就能看出他们的区别:一个是对于引用的值,指向内存里的同一段空间;一个面向的是对象,它对应的是这个对象的一些性质。

重写equals()

在大多数情况下,我们更倾向于用.equals()来比较两个对象是否等价,但是,由于在Object类之中,方法的实现也只是用了==即引用等价性来实现的,所以这就需要我们完成对该方法的重写。

在重写的时候需要注意.equals()满足的那三个性质:
例如:
标准的.equals()写法:.

@Override
	public boolean equals(Object obj) {
		if(obj == this) {
			return true;
		}
		if(!(obj instanceof Class)) {
			return false;
		}
		Class m1 = (Class) obj;
		return m1 .ocpp1 == ocpp1 &&
			   m1 .ocpp2 == ocpp2;
	}

这就满足了那三条性质。
在某些时候,我们可能忽略了某种性质,是的.equals并不满足等价的条件:

	public boolean equals(Object o) {
		if(!(o instanceof Class))
			return false;
		Class cp = (Class)o;
		return super.equals(o) && cp.Classname== Classname;
	}

这里有一个父类的.equals,这就会使得当父类和子类进行.equals比较的时候出现不同的结果,最终违反了对称性。

	public boolean equals(Object o) {
		if(!(o instanceof Class))
			return false;
		if(!(o instanceof Classex))
			return o.equals(this);
		Classexcp = (Classex)o;
		return super.equals(o) && cp.Classname== Classname;
	}

将上面的那个方法修改之后,就是的.equals满足了对称性,但是它又不满足传递性,这是因为在比较的语句中走入了不同的分支,这样就会出现A.equals(B)和B.equals(C)为True,但是A.equals(C)为false的情况。
所以,在重写.equals()方法的时候一定要万分的小心。

之后,完成了这个方法的重写之后,也要注意hashcode方法的改写,两个equal的objects,一定要有同样的hashcode。两个不equal的objects,不一定要有同样的hashcode。

观察等价性和行为等价性

对于可变数据类型,他们有着mutator方法,所以,在判断他们之间的等价性问题的时候就有两种思考方式,一种是观察他们本身是否一致,一种是对于他们的各种方法在进行相同的操作之后,表现出的结果是否一致。所以,这就有了观察等价性和行为等价性两个概念:

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

对可变类型来说,往往倾向于实现严格的观察等价性,但是这是很难实现的,而且,实现的过程中会带来很多问题。

所以,不同的集合类Java的设计者实现了不同的等价性。Date类实现了观察等价性,List类观察等价性,而StringBuilder类直接继承了Object类,实现了行为等价性。

而对于我们自己所编写的可变类型来说,实现行为等价性就可以了,这就可以直接继承Object类中对应的方法,这大大降低了难度,很方便。

综上,等价性问题还是很复杂的,这需要我们细心体会其中的差异,这样才能保证我们自己重写出的方法满足等价性的条件。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值