Java的Object是所有类的父类, 也有几个常用的需要覆写的方法, 比如equals, hashCode和toString.
每次写这几个方法都要做很多重复性的判断, 很多类库提供了覆写这几个方法的工具类, 比如apache commons lang.
Guava也提供了类似的方式, 在JDK7也提供了和Guava类似的方法.
equals
equals是一个经常需要覆写的方法, 可以查看Object的equals方法注释, 对equals有几个性质的要求: 自反性reflexive, 对称性symmetric, 传递性transitive, 一致性consistent. 还有一个要求: 对于所有非null的值x, x.equals(null)都要返回false. (如果你要用null.equals(x)也可以, 会报NullPointerException)
当我们要覆写的类中某些值可能为null的时候, 就需要对null做很多判断和分支处理. 使用Guava的Objects.equal方法可以避免这个问题, 使得equals的方法的覆写变得更加容易, 而且可读性强, 简洁.
Objects.equal("a", "a"); // returns true Objects.equal(null, "a"); // returns false Objects.equal("a", null); // returns false Objects.equal(null, null); // returns true
JDK7新引入了Objects类, 其中有类似的方法equals.
hashCode
要求equals返回true的值, hashCode也返回相同的值. 所以覆写equals方法, 一般都要覆写hashCode方法.
写一个hashCode本来也不是很难, 但是Guava提供给我们了一个更加简单的方法--Objects.hashCode(Object ...), 这是个可变参数的方法, 参数列表可以是任意数量, 所以可以像这样使用Objects.hashCode(field1, field2, ..., fieldn).非常方便和简洁.
JDK7新引入了Objects类, 其中有类似的方法hash.
toString
这个方法是用得最多的, 覆写得最多, 一个好的toString方法对于调试来说是非常重要的, 但是写起来确实很不爽. 幸好我们可以用eclipse的自动生成代码的功能, 也可以使用apache commons lang来自动生成(使用反射), 当然Guava也提供了方法.
// Returns "ClassName{x=1}" Objects.toStringHelper(this) .add("x", 1) .toString(); // Returns "MyObject{x=1}" Objects.toStringHelper("MyObject") .add("x", 1) .toString();
commons lang的生成方式使用了反射, 效率可能会低一点, 但是有个好处, 修改了类中的成员变量, 不需要修改toString方法, 因为是用的反射. 这个还是很方便的.
compare/compareTo
实现Comparator或Comparable接口, 可以实现比较功能, 但是这个方法却并不好重写, 写过的人都知道. 为了简化, Guava提供了ComparisonChain.
ComparisonChain是一个lazy的比较过程, 当比较结果为0的时候, 即相等的时候, 会继续比较下去, 出现非0的情况, 就会忽略后面的比较.
public int compareTo(Foo that) { return ComparisonChain.start() .compare(this.aString, that.aString) .compare(this.anInt, that.anInt) .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast()) .result(); }
下面是一个完整的示例, 展示了这几个方法的使用
import com.google.common.base.Objects; import com.google.common.collect.ComparisonChain; import com.google.common.collect.Ordering; public class Person implements Comparable<Person> { public String name; public String nickname; public Gender gender; public Person(String name, String nickname, Gender gender) { super(); this.name = name; this.nickname = nickname; this.gender = gender; } @Override public int hashCode() { return Objects.hashCode(name, nickname); } @Override public boolean equals(Object obj) { if (obj instanceof Person) { Person that = (Person) obj; return Objects.equal(name, that.name) && Objects.equal(nickname, that.nickname) && Objects.equal(gender, that.gender); } return false; } // @Override // public String toString() { // return Objects.toStringHelper(this) // .add("name", name) // .add("nickname", nickname) // .add("gender", gender) // .toString(); // } @Override public String toString() { return Objects.toStringHelper(this) .addValue(name) .addValue(nickname) .toString(); } public String preferredName() { return Objects.firstNonNull(nickname, name); } @Override public int compareTo(Person that) { return ComparisonChain.start() .compare(this.name, that.name) .compare(this.nickname, that.nickname) .compare(this.gender, that.gender, Ordering.natural().nullsLast()) .result(); } public static void main(String[] args) { Person person = new Person("Jack", "Jackson", Gender.MALE); System.out.println(person); Person person2 = new Person("Jack", "Jackson", Gender.FEMALE); System.out.println(person2.compareTo(person)); System.out.println(person2.equals(person)); } }
因本人水平有限, 欢迎拍砖!
参考资料: