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 用类层次替代标签类。