知识点概要:
- 等价关系
- 不可变类型的等价性
- == 与 equals()
- 实现equals()
- 对象合同
- 可变类型的等价性
- 自动装箱和等价
一、等价关系
ADT的等价关系是基于AF来定义的
等价关系:自反、对称、传递
二、不可变类型的等价性
不可变类型的等价性还是依据与AF,AF映射到同样的结果,则等价。这也就是说,站在外部观察者的角度:对两个对象调用任何相同的操作,都得到相同的结果,这样就会认为这两个对象等价。反之亦然。
三、==与equals()
==:引用等价性,即如果A==B,则A和B指向内存中同一处地址
对于基本数据类型,要采用==判定相等。
equals():对象等价性,即equals会比较对象内容
由于对于不同的类比较是否等价的条件也不一样,因此,在自定义ADT时,需要重写equals()才能正确的进行equals判断。
对于对象类型,使用equals()判定相等,如果使用==,是在判断来年各个对象是否指向内存中的同意地址。
四、实现equals()
这是Object类中默认的equals()函数,在这的equals()是在判断引用等价性,这通常不是程序员所希望的,因此需要重写,以满足对象等价性。
五、对象合同
除非对象被修改了,否则多次调用equals应得到同样的结果
“相等”的对象,其hashCode()的结果必须一致
程序中多次调用同一个对象的hashCode方法,都要返回相同的值
若两个对象相等,则它们的hashCode相等;反之,若两个对象不相等,则它们的hashCode不相等
当重写Object中的equals()时,也要重写hashCode()。
六、可变类型的等价性
在可变类型中,有两种等价性:
观察等价性:在不改变状态的情况下,两个可变对象是否看起来一致
行为等价性:调用对象的任何方法都展示出一致的结果
注意:对于不可变对象,观察等价性和行为等价性是相同的,因为没有mutator方法。
对于可变类型,往往倾向于实现严格的观察等价性。但这也可能导致bug,甚至破坏RI。主要是由于在可变类型的对象包含在HashSet集合中,变量改变后,hashCode也会改变,导致等价性判断失败。
因此,对于可变类型,实现行为等价性即可,也就是说指向同样内存空间的objects才相等,所以对于可变类型没无需重写equals()和hashCode()方法,直接继承Object中的即可。
如果一定要判断两个可变类型变量的观察等价性,最好定义一个新的方法。
七、自动装箱和等价
Java中为每种基本数据类型都提供了对应的包装器类型,让基本类型具备对象的特征,实现更多的功能。
装箱就是将基本数据类型转换为包装器类型。
在判断等价中,由于包装器类型是不可变类型,而基本数据类型是可变类型,在装箱与拆箱的过程中就会在判断相等的过程中产生差异。
就比如:
而x==y 的结果又是False,而再将x和y都转换为int类型,结果又是true。这是基本类型和封装器类型的差异。
自动装箱的过程又如下所示:
标签:知识点,ADT,对象,equals,等价,hashCode,OOP,可变,类型 From: https://www.cnblogs.com/JayLv/p/17416133.html