Google发布了值类型Java的开源库包AutoValue 1.0。方便使用Java创建值类型。
什么是值类型value type?
一个值类型对象value-typed object是指没有标识的对象(注:类似DDD中的值对象),两个值对象只有在它们内部状态等同是才被认为等同,值对象是典型的不可变。
使用Java编写一个值类型非常单调,为了帮助开发人员实现DRY原则,google提供了AutoValue库包能够产生值对象源码,你所要做的就是定义一个值类型抽象规格,AutVlue将完成剩余的事情,产生你规格的具体实现类,这个实现包含值对象的各种属性:hascode, equals, toString的实现,一个构造器能够检查前置条件,所有的必要的getter方法,因为值对象是不可变的,所以没有setter方法。
AutoValue 是作为一个代码生成器,定义好你 的值类型规格后,一个注解处理器会在编译时创建完整的值类型实现类。需要加入项目的编译:
<dependency> <groupId>com.google.auto.value</groupId> <artifactId>auto-value</artifactId> <version>1.0</version> <scope>provided</scope> </dependency>
|
下面是一个复杂数字的值类型规格(抽象类):
import com.google.auto.value.AutoValue; @AutoValue public abstract class Complex { public static Complex createFromCartesian(double real, double imaginary) { return new AutoValue_Complex(real, imaginary); } public static Complex createFromPolar(double r, double theta) { return new AutoValue_Complex(r * Math.cos(theta), r * Math.sin(theta)); } public abstract double getReal(); public abstract double getImaginary(); }
|
注意到@AutoValue元注释,其中定义了抽象的getter方法,为了创建值类型实例,我们定义了一个或更多静态工厂方法,这里提供了两个工厂方法,工厂方法返回的是我们自己的抽象类,当这个类第一次编译AutoValue库包创建下面的实现:
import javax.annotation.Generated; @Generated("com.google.auto.value.processor.AutoValueProcessor") final class AutoValue_Complex extends Complex { private final double real; private final double imaginary; AutoValue_Complex( double real, double imaginary) { this.real = real; this.imaginary = imaginary; } @Override public double getReal() { return real; } @Override public double getImaginary() { return imaginary; } @Override public String toString() { return "Complex{" + "real=" + real + ", " + "imaginary=" + imaginary + "}"; } @Override public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof Complex) { Complex that = (Complex) o; return (Double.doubleToLongBits(this.real) == Double.doubleToLongBits(that.getReal())) && (Double.doubleToLongBits(this.imaginary) == Double.doubleToLongBits(that.getImaginary())); } return false; } @Override public int hashCode() { int h = 1; h *= 1000003; h ^= (Double.doubleToLongBits(real) >>> 32) ^ Double.doubleToLongBits(real); h *= 1000003; h ^= (Double.doubleToLongBits(imaginary) >>> 32) ^ Double.doubleToLongBits(imaginary); return h; } }
|
可见如果你自己编写,需要很多单调的代码。
值得注意的是,第一次编译会有编译错误,因为在工厂方法中引用了AutoValue_Complex ,它第一次不存在,以后再次编译就没有问题了。