第八章ADT和OOP中的等价性

第八章ADT和OOP中的等价性

== vs .equals()

==:引用等价性,比较的他们在内存中的指向,通常对于基本数据类型使用

equals():对象等价性,比较的是对象的内容,通常对对象类型使用

在自定义ADT的时候,应该重写Object中的equals()方法

实现equals方法

在Object中定义的equals方法实现如下:

public class Object{
    ...
    public boolean equals(Object that){
		return this == that;
    }
}

equals中可以使用instanceof或者getClass()方法获取当且的对象的类

hashCode()

hashCode方法主要被使用在collection中。

在java中hash表采用的是数组+链表的实现。所以对于相等的对象象必须有相同的hashCode,对于不相等的对象也可以映射为同样的hashCode,但性能会变差

在Object中定义的hashCode方法实现如下

public class Object{
    ...
    public boolean hashCode(){
		return /* the memory address of this*/;
    }
}

通常在IDEA中可以自动生成equals和hashCode方法。不过需要注意的是对于equals严格来说,需要根据规约来实现,而不是简单地比较每个field是否相等。对于hashCode实现的时候可以利用java提供的Objects.hash来计算hash值。

可变类型的等价性

观察等价性:在不改变状态的情况下,两个mutable对象是否看起来一致(Collections使用这个)

行为等价性:调用对象的任何方法都展示出一致的结果(StringBuilder使用这个)

仅仅依靠观察等价性可能导致bug。比如下面这个例子:

List<String> list = new ArrayList<>();
list.add("a");
Set<List<String>> set = new HashSet<>();
set.add(list);
System.out.println(set.contains(list));//true
list.add("goodbye");
System.out.println(set.contains(list));//false

所以对于可变类型不需要重写equals和hashCode方法

上一篇:实战一(上):业务开发常用的基于贫血模型的MVC架构违背OOP吗?


下一篇:Equality in ADT and OOP