《Effective Java读书笔记》--对于全部对象都通用的方法

equals

若是肯定一个函数不会被调用,请在函数中直接 throws   UnsupportException,防止程序逻辑出错时还默默执行。 java

在改写类的equals方法时,要实现以下的等价关系: 缓存

  • 自反性
  • 传递性
  • 对称性
  • 一致性
  • 非空性——对任意非空引用值x,x.equals(null)必定返回false。

以下的equals代码是一个很好的实践: 函数

public boolean equals(Object o) {
	if (this == o) {
		return true;
	}
	if (!(o instanceof PhoneNum)) {
		return false;
	}
	PhoneNum pn = (PhoneNum) o;
	return pn.areaCode == this.areaCode && pn.num == this.num;
}




  • 传入参数是Object,而不是其余特化类型,保证了equals函数的重写,而不是重载。
  • 用instanceof检测传入类型,传入参数不是指望类型时就返回false。
  • 比较以前,为了能正确访问对象内的成员,先作了类型的强制强制转换。

hashCode

改写equals时,不要忘记同时改写hashCode。在以下程序中,重写了equesl,可是没有重写hashCode,因此输出null,而不是mike。 this

import java.util.HashMap;
import java.util.Map;

public class Test {
	public static void main(String[] args) {
		HashMap m = new HashMap();
		m.put(new PhoneNum(0, 123456), "mike");
		String v = (String) m.get(new PhoneNum(0, 123456));
		System.out.println(v);
	}
}

class PhoneNum {
	private final int areaCode;
	private final int num;

	PhoneNum(int areaCode, int num) {
		this.areaCode = areaCode;
		this.num = num;
	}

	public boolean equals(Object o) {
		if (!(o instanceof PhoneNum)) {
			return false;
		}
		PhoneNum pn = (PhoneNum) o;
		return pn.areaCode == this.areaCode && pn.num == this.num;
	}
}


实现hashCode时,须要注意: spa

  • x.equals(y)返回true时,那么x和y的hashCode必定要返回相同值。
  • 若是对象是非可变的,而且hashCode的计算很耗费资源,建议第一次计算hashCode后,就把它缓存到对象内部。

toString

老是要实现toString方法,System.out.println一个对象时,会调用toString方法。 code

clone

改写clone函数会有不少“坑”,建议不该该去改写clone方法。 对象

能够有其余途径去提供对象拷贝的能力,好比拷贝构造函数。
public Yum(Yum yum);
或者是静态工厂方法:
public static Yum newInstance(Yum yum);

拷贝构造函数有许多优势,好比,能够把类型A拷贝成类型B,而这是clone方法不能实现的。 接口

//该代码经过拷贝构造函数,把LinkedList转换成了ArrayList。
LinkedList<Integer> ll = new LinkedList<Integer>();
ll.add(1);
ll.add(2);
ArrayList<Integer> al = new ArrayList<Integer>(ll);
for (Integer i : al) {
    System.out.println(i);
}

compareTo

实现compareTo接口时,要注意: 资源

  • 传递性。 当x.compareTo(y) > 0 && y.compareTo(z) > 0为真时,则x.compareTo(z) > 0。
  • 相对性。x.compareTo(y) > 0 则y.compareTo(y) < 0。x.compareTo(y)抛异常时,y.compareTo(x)也抛异常。
  • 建议保证 (x.compareTo(y) == 0) == (x.equsls(y))
  • x.compareTo(y) == 0 时,那么x.compareTo(z) 和 y.compareTo(z)返回值同正负。
  • compareTo只是指定了返回值的符号,咱们能够利用这一点来简化比较的代码:
public int compareTo(Object o) {
	PhoneNum pn = (PhoneNum) o; // 和equals方法不一样,这里强制转化时,不须要作类型检查。compareTo(null)和compareTo("TEST")分别抛出NullPointerException和ClassCastException正是咱们想要的。
	int areaCodeDiff = areaCode - pn.areaCode;
	if (0 != areaCodeDiff) {
		return areaCodeDiff;
	}
	return this.num - pn.num;
}
相关文章
相关标签/搜索