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

equals

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

在改写类的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。

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时,需要注意:

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

toString

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

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;
}

你可能感兴趣的:(java,读书笔记,effective,编程实践)