Effctive Java 笔记

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

猜你喜欢

转载自luckywnj.iteye.com/blog/2295739