AutoValue介绍

什么是AutoValue?

AutoValue是一个可以自动为值类(value type)生成诸如equals,hashCode,toString等模板方法的工具。这样就使得程序更加短小,简洁,以及更少的bug。

为什么要使用AutoValue

什么是值类(value type)
这里指的是具有值语义的类型,只要两个实例具有相同的字段值,他们就可以互换。比如DateTime,Money,Uri... 这必须实现equals方法和hashCode方法,通常还会实现toString方法。
看一下实现这样一个值类的基本框架

public final class Foo {
    private final String text;
    private final int number;


    public Foo(String text, int number) {
        this.text = text;
        this.number = number;
    }

    public String text() {
        return text;
    }

    public int number() {
        return number;
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (o instanceof Foo) {
            Foo that = (Foo) o;
            return text.equals(that.text)
                    && number == that.number;
        }
        return false;
    }

    @Override
    public int hashCode() {
        int h$ = 1;
        h$ *= 1000003;
        h$ ^= text.hashCode();
        h$ *= 1000003;
        h$ ^=  number;
        return h$;
    }

    @Override
    public String toString() {
        return "Foo{"
                + "text=" + text + ", "
                + "number=" + number
                + "}";
    }

}

简单的一个类,添加了equals,hashCode,toString方法之后一下子暴增了,并且添加一个字段之后,你不得不修改这几个非常公式化的方法。最坏的情况,添加类似一个值类,你又得重复这些烦人的工作。
为什么会出现这么多的代码?
1,固有的字段构造函数和访问函数
2,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。当向散列集合中插入对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址,所以这里存在一个冲突解决的问题,这样一来实际调用equals方法的次数就大大降低了。
看一个例子

class People{
    private String name;
    private int age;
     
    public People(String name,int age) {
        this.name = name;
        this.age = age;
    }  
     
    public void setAge(int age){
        this.age = age;
    }
         
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        return this.name.equals(((People)obj).name) && this.age== ((People)obj).age;
    }
}
        People p = new People("Jack", 12);
        System.out.println(p.hashCode());
             
        HashMap hashMap = new HashMap();
        hashMap.put(p, 1);
         
        System.out.println(hashMap.get(new People("Jack", 12)));

你觉得会输出1吗?答案是输出null,因为People类没有覆写hashCode方法,导致new 的People与hashMap中的people的hashCode值不一样。所以正确的做法是覆写hashCode方法。
3,equals方法比较两个对象是否相同。
4,toString可以使日志,调式更方便。

怎样使用AutoValue

编写一个类
1,这个类是抽象的
2,抽象的字段访问函数,没有字段。
3,提供一个静态的创建函数返回该类对象
4,类上标记@AutoValue注解

@AutoValue
public abstract class Foo {//1,这个类是抽象的
  //3,提供一个静态的创建函数返回该类对象
  public static Foo create(String text, int number) {
    return new AutoValue_Foo(text, number);//autovalue生成的类名为AutoValue_Foo
  }

  /** Documentation here. */
  public abstract String text(); //2,抽象的字段访问函数,没有字段。

  /** Documentation here. */
  public abstract int number();
}

AutoValue替我们生成的类

final class AutoValue_Foo extends Foo { //注意:该类不是public
  private final String text;
  private final int number;

  AutoValue_Foo(String text, int number) {
    if (text == null) {
      throw new NullPointerException("text");
    }
    this.text = text;
    this.number = number;
  }

  @Override public String text() {
    return text;
  }

  @Override public int number() {
    return number;
  }

   @Override
    public boolean equals(@Nullable Object o) {
        if (o instanceof Foo) {
            Foo that = (Foo) o;
            return text.equals(that.text)
                    && number == that.number;
        }
        return false;
    }

    @Override
    public int hashCode() {
        int h$ = 1;
        h$ *= 1000003;
        h$ ^= text.hashCode();
        h$ *= 1000003;
        h$ ^=  number;
        return h$;
    }

    @Override
    public String toString() {
        return "Foo{"
                + "text=" + text + ", "
                + "number=" + number
                + "}";
    }
}

如果你想使用Builder模式,那么也可以
编写一个类
1,这个类是抽象的
2,抽象的字段访问函数,没有字段。
3,提供一个静态抽象内嵌类Builder,打上@ @AutoValue.Builder注解
4,静态抽象内嵌类Builder提供抽象字段设置方法
5,静态抽象内嵌类Builder提供抽象build方法,返回值是外部类
6,提供一个静态的builder方法返回内嵌类Builder
7,类上标记@AutoValue注解

@AutoValue
public abstract class Foo {

    abstract  String text();
    abstract int number();

    public static Builder builder(){
        return new AutoValue_Foo.Builder();
    }


    @AutoValue.Builder
    abstract static class Builder{

        abstract Builder setText(String text);
        abstract Builder setNumber(int number);
        abstract Foo build();
    }

}

AutoValue替我们生成的类

@Generated("com.google.auto.value.processor.AutoValueProcessor")
 final class AutoValue_Foo extends Foo {

  private final String text;
  private final int number;

  private AutoValue_Foo(
      String text,
      int number) {
    this.text = text;
    this.number = number;
  }

  @Override
  String text() {
    return text;
  }

  @Override
  int number() {
    return number;
  }

  @Override
  public String toString() {
    return "Foo{"
         + "text=" + text + ", "
         + "number=" + number
        + "}";
  }

  @Override
  public boolean equals(Object o) {
    if (o == this) {
      return true;
    }
    if (o instanceof Foo) {
      Foo that = (Foo) o;
      return (this.text.equals(that.text()))
           && (this.number == that.number());
    }
    return false;
  }

  @Override
  public int hashCode() {
    int h$ = 1;
    h$ *= 1000003;
    h$ ^= text.hashCode();
    h$ *= 1000003;
    h$ ^= number;
    return h$;
  }

  static final class Builder extends Foo.Builder {
    private String text;
    private Integer number;
    Builder() {
    }
    @Override
    Foo.Builder setText(String text) {
      if (text == null) {
        throw new NullPointerException("Null text");
      }
      this.text = text;
      return this;
    }
    @Override
    Foo.Builder setNumber(int number) {
      this.number = number;
      return this;
    }
    @Override
    Foo build() {
      String missing = "";
      if (this.text == null) {
        missing += " text";
      }
      if (this.number == null) {
        missing += " number";
      }
      if (!missing.isEmpty()) {
        throw new IllegalStateException("Missing required properties:" + missing);
      }
      return new AutoValue_Foo(
          this.text,
          this.number);
    }
  }

}

你可能感兴趣的:(AutoValue介绍)