Objects工具類,能夠分爲兩部分來分析。一部分是equals()和hashcode()方法的支持。另外一部分是toString()和compareTo()的鏈式調用的支持。java
對於equals()方法,Guava的Objects類提供了以下支持:ide
public static boolean equal(@Nullable Object a, @Nullable Object b){ return a == b || (a != null && a.equals(b)); }
對於hashcode()方法,Guava的Objects類提供了以下支持:工具
public static int hashCode(@Nullable Object... objects) { return Arrays.hashCode(objects); }
equal()方法的實現,比較簡單,採用Objects.equal(a,b),很巧妙的避免了a.equals(b)時,NullPointerException的出現。this
hashcode()方法的實現,也是比較簡單。google
通常狀況下,重寫hashcode()和equals()方法的時候都會使用IDE直接生成,以下所示:spa
public class Person { private int id; private String name; private int age; @Override public int hashCode() { int result = id; result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + age; return result; } }
能夠看出重寫後的方法會讓使用者很困惑,究竟哪些字段參與了比較。而Objects中的hashcode()方法能夠很好的解決這個問題。以下代碼所示:code
public class Person { private int id; private String name; private int age; @Override public int hashCode() { return Objects.hashCode(id, name, age); } }
須要注意的是。在Java7後,Guava讓咱們使用java.util.Objects,替代Guava的Objects,API參數是同樣的。對象
Objects另外一個須要闡述的地方,是對toString()和compare()方法的支持。blog
對於toString()方法的鏈式調用的支持。以下代碼所示:get
public class Person { private int id; private String name; private int age; @Override public String toString() { return MoreObjects.toStringHelper(this).add("id", id).add("name", name).add("age", age).toString(); } }
下面,咱們分析一下MoreObjects.toStringHelper的實現
public static ToStringHelper toStringHelper(Object self) { return new ToStringHelper(simpleName(self.getClass())); }
靜態方法直接返回ToStringHelper對象,接下來鏈式調用add(name,value)方法,而ToStringHelper內部維護一個ValueHolder(name, value,next結構)鏈表,記錄add(name,value)的全部內容
public static final class ToStringHelper { private final String className; private ValueHolder holderHead = new ValueHolder(); private ValueHolder holderTail = holderHead; private boolean omitNullValues = false; }
private ToStringHelper addHolder(String name, @Nullable Object value) { ValueHolder valueHolder = addHolder(); valueHolder.value = value; valueHolder.name = checkNotNull(name); return this; }
還有一個方法。簡單說明一下,代碼以下:
public ToStringHelper omitNullValues() { omitNullValues = true; return this; }
這裏omitNullValues是一個開關,控制是否在ToStringHelper.toString()的時候輸出null值。
另外一個就是對於compare的重寫,這個實現的非常巧妙
@Override public int compareTo(Person o) { return ComparisonChain.start().compare(id, o.id).compare(name, o.name).compare(age, o.age).result(); }
在ComparisonChain中,有三個內部常量
private static final ComparisonChain ACTIVE = new ComparisonChain(); private static final ComparisonChain LESS = new InactiveComparisonChain(-1); private static final ComparisonChain GREATER = new InactiveComparisonChain(1);
在ACTIVE實現中,才真正實現了compare的比較邏輯是就是classify()方法
ComparisonChain classify(int result) { return (result < 0) ? LESS : (result > 0) ? GREATER : ACTIVE; }
LESS和GREATER的區別僅僅在於,構造參數中傳入的int(result)值不一樣,而在InactiveComparisonChain內部實現中,compare方法僅僅返回this,而不去真正執行比較邏輯,由於此階段的比較結果若是是LESS或是GREATER,最終ComparisonChain的結果也就決定了。然後續的比較沒有意義。
private static final class InactiveComparisonChain extends ComparisonChain { final int result; InactiveComparisonChain(int result) { this.result = result; } @Override public ComparisonChain compare( @Nullable Comparable left, @Nullable Comparable right) { return this; } @Override public <T> ComparisonChain compare(@Nullable T left, @Nullable T right, @Nullable Comparator<T> comparator) { return this; } @Override public ComparisonChain compare(int left, int right) { return this; } @Override public ComparisonChain compare(long left, long right) { return this; } @Override public ComparisonChain compare(float left, float right) { return this; } @Override public ComparisonChain compare(double left, double right) { return this; } @Override public ComparisonChain compareTrueFirst(boolean left, boolean right) { return this; } @Override public ComparisonChain compareFalseFirst(boolean left, boolean right) { return this; } @Override public int result() { return result; } }