autovalue_AutoValue:生成的不可变值类

autovalue

Google GitHub托管的项目AutoValue之所以有趣,有多种原因。 该项目不仅使为“ 值对象 ”编写更少的Java代码变得容易,而且还为Java注释处理的实际应用提供了概念上简单的演示。 该自动/值项目是由提供谷歌的员工凯文Bourrillion埃蒙·麦克马纳斯和许可与Apache的版本2的许可

AutoValue用户指南》简短明了,其简洁和简洁反映了项目本身。 用户指南提供了使用AutoValue的简单示例,讨论了为什么需要 AutoValue,在“ 我如何……”部分中对常见问题进行了简短回答,并概述了与使用AutoValue有关的一些最佳做法

下面的代码清单包含一个我手写的简单类,称为Person 。 编写此类时要牢记AutoValue。

人.java

package dustin.examples.autovalue;

import com.google.auto.value.AutoValue;

/**
 * Represents an individual as part of demonstration of
 * GitHub-hosted project google/auto/value
 * (see https://github.com/google/auto/tree/master/value).
 */
@AutoValue  // concrete extension will be generated by AutoValue
abstract class Person
{
   /**
    * Create instance of Person.
    *
    * @param lastName Last name of person.
    * @param firstName First name of person.
    * @param birthYear Birth year of person.
    * @return Instance of Person.
    */
   static Person create(String lastName, String firstName, long birthYear)
   {
      return new AutoValue_Person(lastName, firstName, birthYear);
   }

   /**
    * Provide Person's last name.
    *
    * @return Last name of person.
    */
   abstract String lastName();

   /**
    * Provide Person's first name.
    *
    * @return First name of person.
    */
   abstract String firstName();

   /**
    * Provide Person's birth year.
    *
    * @return Person's birth year.
    */
   abstract long birthYear();
}

当使用AutoValue生成完整的“值类”时,只需为AutoValue提供一个抽象类(故意不支持接口)以生成相应的具体扩展。 该abstract类必须使用@AutoValue批注进行注释,必须提供提供值类实例的static方法,并且必须提供暗示值类的受支持字段的public或包范围的abstract访问器方法。

在上面的代码清单中,静态实例创建方法实例化了AutoValue_Person对象,但是我没有定义这样的AutoValue_Person类。 此类是AutoValue生成的类的名称,该类将在对Person.java进行javac编译时执行AutoValue的注释处理时生成。 由此,我们可以看到AutoValue生成的类的命名约定: AutoValue_放在源类的名称之前,以形成生成的类的名称。

Person.java在编译过程中应用AutoValue注释处理进行编译时,将生成生成的类。 就我而言(使用AutoValue 1.2 / auto-value-1.2.jar ),生成了以下代码:

AutoValue_Person.java:由AutoValue生成

package dustin.examples.autovalue;

import javax.annotation.Generated;

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

  private final String lastName;
  private final String firstName;
  private final long birthYear;

  AutoValue_Person(
      String lastName,
      String firstName,
      long birthYear) {
    if (lastName == null) {
      throw new NullPointerException("Null lastName");
    }
    this.lastName = lastName;
    if (firstName == null) {
      throw new NullPointerException("Null firstName");
    }
    this.firstName = firstName;
    this.birthYear = birthYear;
  }

  @Override
  String lastName() {
    return lastName;
  }

  @Override
  String firstName() {
    return firstName;
  }

  @Override
  long birthYear() {
    return birthYear;
  }

  @Override
  public String toString() {
    return "Person{"
        + "lastName=" + lastName + ", "
        + "firstName=" + firstName + ", "
        + "birthYear=" + birthYear
        + "}";
  }

  @Override
  public boolean equals(Object o) {
    if (o == this) {
      return true;
    }
    if (o instanceof Person) {
      Person that = (Person) o;
      return (this.lastName.equals(that.lastName()))
           && (this.firstName.equals(that.firstName()))
           && (this.birthYear == that.birthYear());
    }
    return false;
  }

  @Override
  public int hashCode() {
    int h = 1;
    h *= 1000003;
    h ^= this.lastName.hashCode();
    h *= 1000003;
    h ^= this.firstName.hashCode();
    h *= 1000003;
    h ^= (this.birthYear >>> 32) ^ this.birthYear;
    return h;
  }

}

通过检查生成的代码可以得出以下几点结论:

  • 生成的类扩展了(实现继承)手写的抽象类,从而允许使用代码使用手写类的API,而不必知道正在使用生成的类。
  • 即使没有在源类中直接定义任何字段,也将生成字段; AutoValue解释了提供的abstract访问器方法中的字段。
  • 生成的类不为字段提供“设置” / mutator方法(get / accessor方法)。 这是AutoValue的故意设计决策 ,因为Value Objects的一个关键概念是它们是不可变的。
  • 考虑到每个字段的类型,将自动为每个字段适当地生成equals(Object)hashCode()toString()的实现。
  • 在源类和方法上的Javadoc注释不会在生成的扩展类上重现。

使用诸如AutoValue生成之类的方法的主要优点之一是,开发人员可以专注于特定类应支持的更简单的高级概念,并且代码生成可确保一致,正确地实现较低级的细节。 但是,使用这种方法时要记住一些事情,文档的“ 最佳实践”部分是一个不错的地方,可以很早阅读,以了解AutoValue的假设是否适合您的情况。

  • 当开发人员受过足够的训练以检查和维护abstract “源” Java类而不是生成的类时,AutoValue很有可能会有所帮助。
    • 下次注释处理再次生成该类时,对生成类的更改将被覆盖,否则必须停止该类的生成,以免发生这种情况。
  • 您将需要设置build / IDE,以便将生成的类视为“源代码”,从而可以编译abstract类。
  • 如果将可变字段与AutoValue一起使用时,如果要保持不变性,则必须格外小心(通常选择使用Value Objects时就是这种情况)。
  • 查看“ 最佳做法”“我如何……”部分,以确保没有任何AutoValue的设计假设使它不利于您的需求。

结论

AutoValue允许开发人员编写更简洁的代码,重点放在高级细节上,并将繁琐的底层(通常是容易出错的)细节的实现委派给AutoValue来自动生成代码。 这类似于IDE的源代码生成可以执行的操作,但是AutoValue优于IDE方法的优点是,AutoValue可以在每次编译代码时重新生成源代码,从而使生成的代码保持最新。 AutoValue的这一优势也是Java自定义注释处理功能的一个很好的例子。

翻译自: https://www.javacodegeeks.com/2016/06/autovalue-generated-immutable-value-classes.html

autovalue

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值