Guava源碼分析——Objects

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;
    }
  }
相關文章
相關標籤/搜索