Lombok常用注解
参考
https://blog.csdn.net/qiushisoftware/article/details/108075920
https://www.cnblogs.com/shihaiming/p/11392983.html
简介
Lombok提供了一系列注解用以在后台生成模板代码,将其从你的类中删除,从而有助于保持你的代码整洁。较少的模板意味着更简洁的代码,更易于阅读和维护。
入参检测:@NonNull、@NotBlank等
public void nonNullDemo(Employee employee, Account account) {
if (employee == null) {
throw new IllegalArgumentException("Employee is marked @NonNull but is null");
}
if (account == null) {
throw new IllegalArgumentException("Account is marked @NonNull but is null");
}
// do stuff
}
用@NonNull标记参数,Lombok替你生成 null 检查。
public void nonNullDemo(@NonNull Employee employee, @NonNull Account account) {
// just do stuff
}
默认情况下, Lombok会抛出 NullPointerException。也可以配置 Lombok抛出 IllegalArgumentException。
其他类似注解:
//被注释的元素必须为null
@Null
//被注释的元素不能为null
@NotNull
//被注释的元素必须为true
@AssertTrue
//被注释的元素必须为false
@AssertFalse
//被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Min(value)
//被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Max(value)
//被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMin(value)
//被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMax(value)
//被注释的元素的大小必须在指定的范围内。
@Size(max,min)
//被注释的元素必须是一个数字,其值必须在可接受的范围内
@Digits(integer,fraction)
//被注释的元素必须是一个过去的日期
@Past
//被注释的元素必须是一个将来的日期
@Future
//被注释的元素必须符合指定的正则表达式。
@Pattern(value)
//被注释的元素必须是电子邮件地址
@Email
//被注释的字符串的大小必须在指定的范围内
@Length
//被注释的字符串必须非空
@NotEmpty
//被注释的元素必须在合适的范围内
@Range
更简洁的数据类
数据类是 Lombok 真正有助于减少模板代码的领域。
数据类通常包括以下一种或全部:
构造函数(有或没有参数)
私有成员变量的 getter 方法
私有非 final 成员变量的 setter 方法
帮助记录日志的 toString 方法
equals 和 hashCode(处理相等/集合)
@Getter 和 @Setter
Lombok可以替你生成 getter和 setter模板。通过对每个成员变量使用 @Getter和 @Setter注解,你最终得到一个等效的类,如下所示:
public class Car {
@Getter
@Setter
private String make;
@Getter
@Setter
private String model;
@Getter
@Setter
private String bodyType;
@Getter
@Setter
private int yearOfManufacture;
@Getter
@Setter
private int cubicCapacity;
}
注意,只能在非 final 成员变量上使用 @Setter,在 final成员变量上使用将导致编译错误。
如果需要为每个成员变量生成 getter和 setter,可以在类级别使用 @Getter和 @Setter,如下所示。
@Getter
@Setter
public class Car {
private String make;
private String model;
private String bodyType;
private int yearOfManufacture;
private int cubicCapacity;
}
@AllArgsConstructor
数据类通常包含一个构造函数,它为每个成员变量接受参数。IDE 为 Car 生成的构造函数如下所示:
public class Car {
@Getter
@Setter
private String make;
@Getter
@Setter
private String model;
@Getter
@Setter
private String bodyType;
@Getter
@Setter
private int yearOfManufacture;
@Getter
@Setter
private int cubicCapacity;
public Car(String make, String model, String bodyType, int yearOfManufacture, int cubicCapacity) {
super();
this.make = make;
this.model = model;
this.bodyType = bodyType;
this.yearOfManufacture = yearOfManufacture;
this.cubicCapacity = cubicCapacity;
}
}
我们可以使用 @AllArgsConstructor 注解实现同样功能。 使用 @Getter 和 @Setter、 @AllArgsConstructor可以减少模板,保持类更干净且更简洁。
@AllArgsConstructor
public class Car {
@Getter
@Setter
private String make;
@Getter
@Setter
private String model;
@Getter
@Setter
private String bodyType;
@Getter
@Setter
private int yearOfManufacture;
@Getter
@Setter
private int cubicCapacity;
}
还有其他选项用于生成构造函数。 @RequiredArgsConstructor 将创建带有每个 final成员变量参数的构造函数, @NoArgsConstructor
将创建没有参数的构造函数。
@ToString
在你的数据类上覆盖 toString方法是有助于记录日志的良好实践。IDE 为 Car类生成的 toString方法如下所示:
@AllArgsConstructor
public class Car {
@Getter
@Setter
private String make;
@Getter
@Setter
private String model;
@Getter
@Setter
private String bodyType;
@Getter
@Setter
private int yearOfManufacture;
@Getter
@Setter
private int cubicCapacity;
@Override
public String toString() {
return "Car [make=" + make + ", model="
+ model + ", bodyType=" + bodyType + ", yearOfManufacture="
+ yearOfManufacture + ", cubicCapacity=" + cubicCapacity
+ "]";
}
}
我们可以使用 ToString注解替换这个,如下所示:
@ToString
@AllArgsConstructor
public class Car {
@Getter
@Setter
private String make;
@Getter
@Setter
private String model;
@Getter
@Setter
private String bodyType;
@Getter
@Setter
private int yearOfManufacture;
@Getter
@Setter
private int cubicCapacity;
}
默认情况下,Lombok 生成包含所有成员变量的 toString 方法。可以通过 exclude 属性 @ToString(exclude={“someField”},“someOtherField”}) 覆盖行为将某些成员变量排除。
@EqualsAndHashCode
如果你正在将你的数据类和任何类型的对象比较,则需要覆盖 equals和 hashCode 方法。对象的相等是基于业务规则定义的。举个例子,在 Car类中,如果两个对象有相同的 make、 model和 bodyType,我可能认为他们是相等的。如果我使用 IDE 生成 equals 方法检查 make、 model 和 bodyType,它看起来会是这样:
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Car other = (Car) obj;
if (bodyType == null) {
if (other.bodyType != null)
return false;
} else if (!bodyType.equals(other.bodyType))
return false;
if (make == null) {
if (other.make != null)
return false;
} else if (!make.equals(other.make))
return false;
if (model == null) {
if (other.model != null)
return false;
} else if (!model.equals(other.model))
return false;
return true;
}
等价的 hashCode 实现如下所示:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((bodyType == null) ? 0 : bodyType.hashCode());
result = prime * result + ((make == null) ? 0 : make.hashCode());
result = prime * result + ((model == null) ? 0 : model.hashCode());
return result;
}
虽然 IDE 处理了繁重的工作,但我们在类中仍然有大量的模板代码。 Lombok允许我们使用 @EqualsAndHashCode 类注解实现相同的功能,如下所示:
@ToString
@AllArgsConstructor
@EqualsAndHashCode(exclude = {"yearOfManufacture", "cubicCapacity"})
public class Car {
@Getter
@Setter
private String make;
@Getter
@Setter
private String model;
@Getter
@Setter
private String bodyType;
@Getter
@Setter
private int yearOfManufacture;
@Getter
@Setter
private int cubicCapacity;
}
默认情况下,@EqualsAndHashCode 会创建包含所有成员变量的 equals 和 hashCode 方法。 exclude选项可用于通知 Lombok排除某些成员变量。在上面的代码片段中。我已经从生成的 equals和 hashCode方法中排除了 yearOfManuFacture 和 cubicCapacity。
@Data = @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor
如果你想使数据类尽可能精简,可以使用 @Data 注解。 @Data 是 @Getter、 @Setter、 @ToString、 @EqualsAndHashCode 和 @RequiredArgsConstructor 的快捷方式。
@ToString
@RequiredArgsConstructor
@EqualsAndHashCode(exclude = {"yearOfManufacture", "cubicCapacity"})
public class Car {
@Getter
@Setter
private String make;
@Getter
@Setter
private String model;
@Getter
@Setter
private String bodyType;
@Getter
@Setter
private int yearOfManufacture;
@Getter
@Setter
private int cubicCapacity;
}
通过使用 @Data,我们可以将上面的类精简如下:
@Data
public class Car {
private String make;
private String model;
private String bodyType;
private int yearOfManufacture;
private int cubicCapacity;
}
使用 @Buidler 创建对象
建造者设计模式描述了一种灵活的创建对象的方式。 Lombok可以帮你轻松的实现该模式。看一个使用简单 Car 类的示例。假设我们希望可以创建各种 Car对象,但我们希望在创建时设置的属性具有灵活性。
Lombok通过 @Builder 注解帮你实现建造者模式。当你使用 @Builder 注解 Car 类时, Lombok会执行以下操作:
添加一个私有构造函数到 Car
创建一个静态的 CarBuilder 类
在 CarBuilder 中为 Car 中的每个成员创建一个 setter风格方法
在 CarBuilder中添加创建 Car 的新实例的建造方法
CarBuilder上的每个 setter 风格方法返回自身的实例( CarBuilder)。这允许你进行方法链式调用并为对象创建提供流畅的 API。让我们看看它如何使用。
Car muscleCar = Car.builder().make("Ford")
.model("mustang")
.bodyType("coupe")
.build();
现在只使用 make 和 model 创建 Car 比之前更简洁了。只需在 Car 上简单的调用生成的 builder 方法获取 CarBuilder 实例,然后调用任何我们感兴趣的 setter 风格方法。最后,调用 build 创建 Car 的新实例。
另一个值得一提的方便的注解是 @Singular。默认情况下,Lombok 为集合创建使用集合参数的标准的 setter 风格方法。在下面的例子中,我们创建了新的 Car 并设置了服务日期列表。
@Builder
public class Car {
private String make;
private String model;
private String bodyType;
private int yearOfManufacture;
private int cubicCapacity;
@Singular
private List<LocalDate> serviceDate;
}
向集合成员变量添加 @Singular 将提供一个额外的方法,允许你向集合添加单个项。
Car muscleCar3 = Car.builder()
.make("Ford")
.model("mustang")
.serviceDate(LocalDate.of(2016, 5, 4))
.build();
现在我们可以添加单个服务日期,如下所示:
Car muscleCar3 = Car.builder()
.make("Ford")
.model("mustang")
.serviceDate(LocalDate.of(2016, 5, 4))
.build();
这是一个有助于在创建对象期间处理集合时保持代码简洁的快捷方法。
如果需要在builder中屏蔽类的某几个字段,参考:
https://www.codenong.com/30717640/
1,字段添加final,static或static final会指示@Builder忽略此字段。
2,使用@Builder标注在自定义构造器上,示例如下:
注意:多个@Builder出现的bug
如下两个会出现串方法的问题,本该进入方法一的但是进入了方法二。导致出现问题。
@Builder
public MyException(Exception Exception, String cause, String suggestion, String detailMessage) {
super(bizException.getMessage());
this.detailMessage = bizException.getMessage() + ". " + detailMessage;
String message = I18nTranslateService.translate(RequestContext.getLanguage(), bizException.getI18nString());
this.errorCode = CommonErrorCode.DEFAULT_ERROR_WITH_INPUT;
this.pushLocalMap("defaultMessage", message);
this.pushLocalMap("cause", cause);
this.pushLocalMap("suggestion", suggestion);
buildErrorInfoI18nTemplate(errorCode);
}
@Builder
public MyException(String errorMsg, String cause, String suggestion, String detailMessage) {
this.errorCode = CommonErrorCode.DEFAULT_ERROR_WITH_INPUT;
buildErrorInfoI18nTemplate(errorCode);
this.pushLocalMap("defaultMessage", errorMsg);
this.pushLocalMap("cause", cause);
this.pushLocalMap("suggestion", suggestion);
this.detailMessage = detailMessage;
}
日志
Lombok另一个伟大的功能是日志记录器。如果没有 Lombok,要实例化标准的 SLF4J日志记录器,通常会有以下内容:
public class SomeService {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
public void doStuff() {
log.debug("doing stuff....");
}
}
这些日志记录器很沉重,并为每个需要日志记录的类添加了不必要的混乱。值得庆幸的是 Lombok提供了一个为你创建日志记录器的注解。你要做的所有事情就是在类上添加注解,这样就可以了。
@Slf4j
public class SomeService {
public void doStuff() {
log.debug("doing stuff....");
}
}
我在这里使用了 @SLF4J注解,但 Lombok能为几乎所有通用 Java日志框架生成日志记录器。有关更多日志记录器的选项,请参阅文档。