Guava源码分析——Objects

Objects工具类,可以分为两部分来分析。一部分是equals()和hashcode()方法的支持。另一部分是toString()和compareTo()的链式调用的支持。

对于equals()方法,Guava的Objects类提供了如下支持:

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的出现。

hashcode()方法的实现,也是比较简单。

一般情况下,重写hashcode()和equals()方法的时候都会使用IDE直接生成,如下所示:

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()方法可以很好的解决这个问题。如下代码所示:

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()方法的支持。

对于toString()方法的链式调用的支持。如下代码所示:

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

 

posted @ 2015-05-27 16:46  PoNa  阅读(1241)  评论(0编辑  收藏  举报