第八章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方法