Software Construction Note 3.5
1. 简介
引用等价和对象等价
观察性等价和行为性等价
2. 3种描述方式
1)AF映射函数(R->A)
2)等价二元关系
3)observation:同一操作得到相同结果(观察性等价)
3. ==和equals()
==:引用等价(原始数据类型必须使用)
equals():对象/内容等价
可依据等价的含义重写equals()
4. immutable
equals默认行为与==相同(所以需要重写,例如String类的equals就是重写过后的)
(hashCode默认行为是返回对象的内存地址)
类型下转是安全的,上转通常不安全(会损失属性)
instanceof:检查对象类型(是动态类型检查,所以尽量避免)
5. Object
重写equals的要求:满足等价性(自反对称传递),一致性(未修改则多次比较结果相同),equals相等则hashCode也必须相等。
equals是所有对象的全局等价关系(对所有对象都生效)
哈希表:键值映射,查找为O(n),优于tree和List,尽量均匀分布,键值对列表(index冲突时)
hashCode要求:多次调用(未修改)结果相同,但不要求程序多次执行结果相同;要求equals等则hashCode等,equals不等则hashCode不一定不等(最好不等)
【重写equals时也必须重写hashCode
(print false)
6. mutable
观察等价:在不改变对象状态的情况下(不使用mutator),无法区分。❌
行为等价:在改变一个对象而不改变另一个时,仍然无法区分。✔
(对于immutable,观察等价和行为等价是相同的/一致的)
(使用观察等价的潜在问题)
List<String> list=new ArrayList<>();
list.add("a");
Set<List<String>> set=new HashSet<List<String>>();
set.add(list);
list.add("good");
set.contains(list) ->false
for(List<String> l:set){
set.contains(l) ->false
}
7. equals()和hashCode()
不可变类型应该重写,可变类型应该继承/默认实现
8. autoBoxing
Integar x=Integar.valueOf(300);
Integar y=Integar.valueOf(300);
x.equals(y) //true
x==y //false