Effctive_Java--笔记&心得

来源:互联网 发布:专家系统原理与编程 编辑:程序博客网 时间:2024/06/09 16:35

equals && hashCode

  • 重写equals方法,只适合值类(枚举类除外)
  • 重新equals方法(普遍的等价关系),需遵循的约定:
    1. 自反性:x.equals(x)==true
    2. 对称性: x.equals(y)==true 必然 y.equals(x)==true
    3. 传递性: x.equals(y)==true, y.equals(z)==true 必然 x.equals(z)==true
    4. 一致性:多次执行结果一致。
  • 重写equals,必须重写hashCode, equals相等hashCode必须相等。hashMap,hashSet需要。

  • 无法再扩展可实例化类(写子类)的同时,既增加值组件,又保留equals约定

    1. 详见”代码-1”
    2. 解决方式:1,用组合代替继承。2,值组件加到抽象类中。
    3. 代码-1:
Piont p = Piont(x,y);Point3D p3d = Point3D(x,y,z);p.equals(p3d) == true;p3d.equals(p) == false

封装、继承、组合(组合优于继承+自己的心得)

  • 封装:隐藏实现细节,改变细节而不影响接口/服务/使用
    1. 函数/方法是封装,类也是封装。
    2. 目的:解放精力在更高的层次上考虑和解决问题
  • 复用的两种方式:继承、组合
  • 继承的优缺点:
    1. 优点: 很方便的复用,比组合复用方便的多
    2. 缺点: 可能会破坏封装
  • 继承可能会破坏封装的分析:
    1. 子类依赖于父类的实现细节,子类在继承时需要关注父类的实现细节;父类在修改内部实现时,需要考虑对子类的影响。详见”代码-1”,”代码-2”
    2. 子类重写父类方法,可能会违背父类方法的声明
    3. 方法调用不会依赖实现细节,
  • 如何正确使用继承:
    1. 要么为继承而设计,并提供文档说明,要么就禁止继承–原书第17章
      • 文档必须说明每个可覆盖的方法的自用性
      • 文档必须精确地描述覆盖每个方法所带来的影响
      • 上述两条违背了”文档应该描述做什么,而不是怎么做”,这是继承破坏封装带来的恶果。
      • 构造器决不能调用可被覆盖的方法,无论是直接调用还是间接调用
      • 不可覆盖的方法: 使用final或者private修饰
      • 不可被继承的类: 使用final修饰类,private修饰所有构造(然后提供工厂方法)
  • 代码-2:
/** * 1,子类MyHashSet的addAll(),势必要考虑父类addAll()的实现细节。 * 2,父类未来修改addAll()的内部实现,很可能会影响到子类的正确性。 */public class MyHashSet<E> extends HashSet<E>{    private int addCount = 0;    public boolean add(E e) {        addCount++;        return super.add(e);    }    /**     * 父类,子类各自的实现细节及依赖:     * <pre>     *     1, 父类HashSet.addAll()-->父类HashSet.add()     *     2, 子类MyHashSet.addAll()-->父类HashSet.addAll()-->子类MyHashSet.add() //因为多态     * </pre>     */    public boolean addAll(Collection<? extends E> c) {        addCount += c.size();        return super.addAll(c);    }    public int getAddCount() {        return addCount;    }    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());      }}

其他准则

  • 始终覆盖toString
  • 使类和成员的访问下最小。以后再改大。
  • 接口优于抽象类
  • 接口只用于定义类型
  • 用类层次替代标签类