8,重写equals,只适合值类(枚举类除外)
自反性:x.equals(x)==true
对称性: x.equals(y)==true 必然 y.equals(x)==true
传递性: x.equals(y)==true, y.equals(z)==true 必然 x.equals(z)==true
一致性:多次执行结果一直。
问题:无法再扩展可实例化类(写子类)的同时,既增加值组件,又保留equals约定。
如Piont(x,y),Point3D(x,y,z)。p.equals(p3d) == true, p3d.equals(p) == false
解决方式:1,用组合代替继承。2,值组件加到抽象类中。
9,重写equals,必须重写hashCode
equals相等必须hashCode相等。hashMap,hashSet需要。
10,始终覆盖toString
chapter-4 类和接口
13,使类和成员的访问下最小。以后再改大。
16,组合优于继承
继承会破坏封装。例子。
package study.timeriver.wnj;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
public class Test {
//继承破坏封装。super.addAll()原本调用的是HashSet的add()。现在变成了调用MyHashSet.add()
//addAll()调用add()是自用(self-use)。是实现细节。不是接口承诺。
//例子2:子类所有的add()都会验证,如果父类又新增了一个addX(),但没有验证。使用子类对象就可以调用addX()。这就破坏了子类的封装。可以加入非法元素了。
//例子3:父类新增一个子类的方法。会直接编译错误。
public static void main(String[] args) {
MyHashSet<String> s = new MyHashSet<String>();
s.addAll(Arrays.asList("a", "b", "c"));
//输出是6,不是3。
System.out.println(s.getAddCount());
}
static class MyHashSet<E> extends HashSet<E> {
private int addCount = 0;
public boolean add(E e) {
addCount++;
return super.add(e);
}
public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c);
}
public int getAddCount() {
return addCount;
}
}
}
使用组合就可以避免。
17,要么为继承设计,并提供文档。要么禁止继承。
说明那些方法可以覆盖,如何覆盖。
18,接口优于抽象类
19,接口只用于定义类型
20 用类层次替代标签类。