Avery's Blog

Work on Web Dev, Infra Dev & ML

0%

一文了解 Lombok 常用注解和隐藏坑点

看完这篇,你就是 Lombok 大师。

@Data

@Data 注解:@ToString, @EqualsAndHashCode, @Getter on all fields, @Setter on all non-final fields, and @RequiredArgsConstructor

需要注意的是,如果存在任何写明的构造器,@Data 注解不会再生成新的构造器。

@Builder

@Builder 注解:允许 Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build(); 的形式创建对象。

需要注意的是,@Builder 注解生成的 AllArgsConstructor 默认是 @AllArgsConstructor(access = AccessLevel.PACKAGE),即构造器上没有 public 标识符,所以跨包生成时可能会出现访问权限问题。

此外,@Builder@Data 注解同时存在时,先生成包访问权限的 AllArgsConstructor,且因为有了构造器,@Data 注解不会再生成 RequiredArgsConstructor,因此结果是只有一个包访问权限的 AllArgsConstructor,因此需要再手动声明 @AllArgsConstructor@RequiredArgsConstructor。不建议声明 @NoArgsConstructor,因为此构造器可以逃逸 Lombok 对 @NonNull 注解字段的 null-check。如果框架要求或其他情况非要使用,建议使用 @NoArgsConstructor(onConstructor = @__({@Deprecated})) 表明该接口已废弃防止手动使用。

构造器们

@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor: generates constructors that take no arguments, one argument per final / non-null field, or one argument for every field.

这三个构造器注解和其他 Lombok 注解不同,即便有同名、同入参个数的方法存在,也会生成构造方法。如果签名还恰巧一致,则会抛出编辑器错误。

@EqualsAndHashCode

@EqualsAndHashCode: generate implementations of the equals(Object other) and hashCode() method. By default, it’ll use all non-static, non-transient fields.

@EqualsAndHashCode 默认是 callSuper = false 的,意思是只要两个子类的独有属性相同,即为相同。如果还要比较从父类继承的属性,需要设置 callSuper = true

@Value

@Value: @Data 注解的不可变形式,不含 @Setter@RequiredArgsConstructor 改为 @AllArgsConstructor

@NonNull

@NonNull 注解能和 @Builder注解良好合作。在 POJO 上的 @NonNull 注解可以防止 set 入 null 值,防止构造器传入 null 值;在传入参数上的 @NonNull 注解可以防止参数为 null,参考链接

但是 Lombok 的 @NoArgsConstructor 注解不会进行 null-check,参考链接。所以说,无参构造器可以逃逸 null-check 检查,建议在无参构造器上增加 @Deprecated 注解。

Delombok

Lombok 是绝对有用的,就算是组织或公司不允许使用 Lombok,也可以在 IDEA 中 delombok 把注解转换成生成的代码。这个也可以用于排查 Lombok 导致的疑难杂症。

最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
@Data
@Builder
@AllArgsConstructor
@RequiredArgsConstructor
@NoArgsConstructor(onConstructor = @__({@Deprecated})) // 非必要不使用
public class BestPractice {

private String nullableStr;

@NonNull
private String mainStr;
}

Welcome to my other publishing channels