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;}@OverrideString lastName() {return lastName;}@OverrideString firstName() {return firstName;}@Overridelong birthYear() {return birthYear;}@Overridepublic String toString() {return "Person{"+ "lastName=" + lastName + ", "+ "firstName=" + firstName + ", "+ "birthYear=" + birthYear+ "}";}@Overridepublic 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;}@Overridepublic 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