@Value
不可变的类变得非常容易。
@Value
在lombok v0.11.4中作为实验特征引入。
@Value @Wither
自从lombok v0.11.8以来不再暗示。
@Value lombok
自lombok v0.12.0以来升级到主程序包。
Overview
@Value
是不可变的变体@Data
; 所有字段由private
和final
默认情况下,也不会产生setter方法。类本身也是final
默认生成的,因为不可变性不是可以强制进入子类的东西。像@Data
,有用的toString()
,equals()
并且hashCode()
也被生成的方法,每个字段得到,其覆盖每个参数(除了吸气剂的方法,和一个构造final
了在字段声明初始化字段)也被产生。
在实践中,@Value
是:的简写final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter
,除了明确包括任何相关方法的实现只是意味着不会生成部分并且不会发出警告。例如,如果您自己编写toString
,则不会发生错误,并且lombok不会生成错误toString
。此外,任何显式构造函数,无论参数列表,都意味着lombok不会生成构造函数。如果你确实希望lombok生成all-args构造函数,请添加@AllArgsConstructor
到类中。您可以标记任何构造函数或方法,@lombok.experimental.Tolerate
以隐藏它们从lombok。
可以使用字段上的显式访问级别或使用@NonFinal
或@PackagePrivate
注释来覆盖默认的最终行为和默认的私有行为。
可以@Value
通过显式使用该批注来覆盖任何组成的“零件”的任何默认行为。
With Lombok
import lombok.AccessLevel;
import lombok.experimental.NonFinal;
import lombok.experimental.Value;
import lombok.experimental.Wither;
import lombok.ToString;
@Value public class ValueExample {
String name;
@Wither(AccessLevel.PACKAGE) @NonFinal int age;
double score;
protected String[] tags;
@ToString(includeFieldNames=true)
@Value(staticConstructor="of")
public static class Exercise<T> {
String name;
T value;
}
}
Vanilla Java
import java.util.Arrays;
public final class ValueExample {
private final String name;
private int age;
private final double score;
protected final String[] tags;
@java.beans.ConstructorProperties({"name", "age", "score", "tags"})
public ValueExample(String name, int age, double score, String[] tags) {
this.name = name;
this.age = age;
this.score = score;
this.tags = tags;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public double getScore() {
return this.score;
}
public String[] getTags() {
return this.tags;
}
@java.lang.Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof ValueExample)) return false;
final ValueExample other = (ValueExample)o;
final Object this$name = this.getName();
final Object other$name = other.getName();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
if (this.getAge() != other.getAge()) return false;
if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
return true;
}
@java.lang.Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
final Object $name = this.getName();
result = result * PRIME + ($name == null ? 43 : $name.hashCode());
result = result * PRIME + this.getAge();
final long $score = Double.doubleToLongBits(this.getScore());
result = result * PRIME + (int)($score >>> 32 ^ $score);
result = result * PRIME + Arrays.deepHashCode(this.getTags());
return result;
}
@java.lang.Override
public String toString() {
return "ValueExample(name=" + getName() + ", age=" + getAge() + ", score=" + getScore() + ", tags=" + Arrays.deepToString(getTags()) + ")";
}
ValueExample withAge(int age) {
return this.age == age ? this : new ValueExample(name, age, score, tags);
}
public static final class Exercise<T> {
private final String name;
private final T value;
private Exercise(String name, T value) {
this.name = name;
this.value = value;
}
public static <T> Exercise<T> of(String name, T value) {
return new Exercise<T>(name, value);
}
public String getName() {
return this.name;
}
public T getValue() {
return this.value;
}
@java.lang.Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof ValueExample.Exercise)) return false;
final Exercise<?> other = (Exercise<?>)o;
final Object this$name = this.getName();
final Object other$name = other.getName();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
final Object this$value = this.getValue();
final Object other$value = other.getValue();
if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false;
return true;
}
@java.lang.Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
final Object $name = this.getName();
result = result * PRIME + ($name == null ? 43 : $name.hashCode());
final Object $value = this.getValue();
result = result * PRIME + ($value == null ? 43 : $value.hashCode());
return result;
}
@java.lang.Override
public String toString() {
return "ValueExample.Exercise(name=" + getName() + ", value=" + getValue() + ")";
}
}
}
Supported configuration keys:
lombok.value.flagUsage = [warning | error] (default: not set)
lombok.val.flagUsage = [warning | error] (default: not set)
Small print
查找文档上的“零件” @Value
:@ToString
,@EqualsAndHashCode
,@AllArgsConstructor
,@FieldDefaults
,和@Getter
。
对于具有泛型的类,使用静态方法作为构造函数是有用的,因为通过静态方法推断泛型参数在java6中工作并避免必须使用菱形运算符。虽然您可以通过应用显式@AllArgsConstructor(staticConstructor="of")
注释来强制执行此操作,但还有一个@Value(staticConstructor="of")
功能,它将使生成的所有参数构造函数成为私有,并生成一个名为public的公共静态方法of
,该方法是此私有构造函数的包装器。
各种众所周知的关于nullity的注释会导致插入空检查并将其复制到相关位置(例如getter的方法,以及构造函数和setter的参数)。有关详细信息,请参阅Getter / Setter文档的小字体。
@Value
是从v0.11.4到v0.11.9(as @lombok.experimental.Value
)的实验性特征。它已被移入核心包中。旧注释仍然存在(并且是别名)。不过,它最终将在未来版本中删除。
无法使用@FieldDefaults
“撤消”带注释的类中字段的默认默认和最终默认方面。使用@NonFinal
和@PackagePrivate
类中的字段来覆盖此行为。