当前位置 : 首页 » 文章分类 :  开发  »  Lombok

Lombok

Lombok 笔记
https://projectlombok.org

Lombok:让JAVA代码更优雅
http://blog.didispace.com/java-lombok-1/


常用注解

@Data

注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
@Data 是 @Getter、 @Setter、 @ToString、 @EqualsAndHashCode 和 @RequiredArgsConstructor 的快捷方式。

Generating equals/hashCode implementation but without a call to superclass

@Data 报 warning
Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add ‘(callSuper=false)’ to your type.

原因:
Lombok @Data 注解在子类上时 IDEA 会给出这个提示,原因是生成的 equals/hashcode 方法没有涵盖父类的字段

解决:
1、加上 @EqualsAndHashCode(callSuper = true)
2、在 src/main/java 文件夹下加 lombok 统一配置文件

config.stopBubbling=true
lombok.equalsAndHashCode.callSuper=call
lombok.addLombokGeneratedAnnotation=true

@NoArgsConstructor

注解在类上;为类提供一个无参的构造方法

@AllArgsConstructor

注解在类上;为类提供一个全参的构造方法


@RequiredArgsConstructor

注解在类上;为类提供一个必要参数的构造方法
什么是必要参数?
1、未初始化的 final 修饰的成员变量
2、@NonNull 修饰的成员变量

另外,如果所有的属性都没有final修饰的话,使用 @RequiredArgsConstructor 会生成一个无参的构造器。

构造器注入与@RequiredArgsConstructor结合

构造器结合 lombok 的 @RequiredArgsConstructor 一起使用,会让代码更加简单

@Component
@RequiredArgsConstructor
public class ThankingService {

    private final Translator translator;

    public String produce() {
        return translator.translate("thank you");
    }
}

等价于

@Component
public class ThankingService {

    private final Translator translator;

    public String thank() {
        return translator.translate("thank you");
    }

    /* Generated by Lombok */
    public ThankingService(Translator translator) {
        this.translator = translator;
    }
}

由于只有一个构造方法,Spring 可以唯一选择这个构造方法来初始化 ThankingService 并自动注入 Translator 实例。

Constructor Injection in Spring with Lombok
https://www.baeldung.com/spring-injection-lombok


@Buidler 建造者模式

实现建造者模式

当你使用 @Builder 注解 User 类时, Lombok 会执行以下操作:
加一个私有构造函数到 User
创建一个静态的 UserBuilder 类
在 UserBuilder 中为 User 中的每个成员创建一个 setter 风格方法
在 UserBuilder 中添加创建 User 的新实例的建造方法

@SuperBuilder 继承父类属性的构造器

@Buidler 只能针对当前类的 field 生成构造器,无法继承父类的 field, 即使给父类也添加 @Builder 注解也依然不能通过链式调用给父类 field 赋值。

Lombok 在 v1.18.2 版本中针对这个问题增加了 @SuperBuilder 注解,子类和父类中都添加 @SuperBuilder 注解,子类 builder 即可继承父类 builder。

@Builder.Default builder默认值

如果不加 @Builder.Default 的话,通过 builder 构建的 PageRequest 的 pageRequest 字段是没有默认值的,必须加上 @Builder.Default 才有

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class PageRequest {
    @Builder.Default
    private ApiPageRequest pageRequest = ApiPageRequest.builder().pageNumber(1).pageSize(20).build();
}
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "user", uniqueConstraints = {@UniqueConstraint(name = "uk_name", columnNames = {"name"})})
public class UserDO {
    private String name;

    /**
     * 状态 enabled/disabled
     */
    @Enumerated(EnumType.STRING)
    @ColumnDefault("'ENABLED'")
    @Builder.Default
    private StatusEnum status = StatusEnum.ENABLED;
}

@SLF4J

https://projectlombok.org/features/log

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);

https://projectlombok.org/features/experimental/SuperBuilder

@UtilityClass 标识工具类

工具类中所有方法都必须是 static 的,不能有任何实例

https://projectlombok.org/features/experimental/UtilityClass


@EqualsAndHashCode

https://projectlombok.org/features/EqualsAndHashCode

@EqualsAndHashCode 用于自动生成 equals(Object other)hashCode() 方法。
默认会使用全部 非 static、非 transient 的字段,但也可以手动指定。
可以在字段上注解 @EqualsAndHashCode.Include 来指定包含,或者注解 @EqualsAndHashCode.Exclude 来指定排除。
还可以通过在指定字段上注解 @EqualsAndHashCode.Include 并使用 @EqualsAndHashCode(onlyExplicitlyIncluded = true) 来完全手动指定包含的字段。

对于有父类的情况,加 callSuper=true 属性会使得生成的 equals(Object other)hashCode() 方法内部调用父类的 equals(Object other)hashCode() 方法。


@ToString.Exclude

注解需要从 toString 方法排除的字段

@SneakyThrows 优雅抛出受检异常

@SneakyThrows 注解在会抛出受检异常的方法上,相当于直接将受检异常抛出。但这么写不用显式 throw,也不用 try catch,非常简洁。

@SneakyThrows
public void sneakyThrows() {
    throw new Exception("exp");
}

反 lombok 后是:

public void sneakyThrows() {
    try {
      throw new Exception("exp");
    } catch (Throwable t) {
      throw Lombok.sneakyThrow(t);
    }
}

实际上等于

public void sneakyThrows() throw Exception {
    throw new Exception("exp");
}

内部实现是利用泛型将 Throwable 强转为 RuntimeException 抛出以达到欺骗 java 编译器的目的,编译器看到是 RuntimeException 就不做检查,但实际运行中 泛型擦除 后还是抛出原异常,异常不会被吞掉。

package lombok;
public class Lombok {
    public static RuntimeException sneakyThrow(Throwable t) {
        if (t == null) throw new NullPointerException("t");
        return Lombok.<RuntimeException>sneakyThrow0(t);
    }
    private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
        throw (T)t;
    }
}

lombok.config

可通过 lombok.config 配置文件配置 lombok 属性,可以放在任何目录,作用于该目录和其子目录
config.stopBubbling=true 指明lombok的根目录为当前配置文件所在目录


问题

编译错误:无法将类 A 中的构造器 A应用到给定类型

java重要特性:子类除了拥有自己的特性外还拥有父类的特性。
因此在初始化子类的时候,父类也要被初始化。
比如定义了类

class A {
  //这样系统不会为类A自动加上无参的构造函数
  public A(int x){}
}

class B extends A {
  //这样系统会自动为B加上无参的构造函数,而且在这个构造函数里有一句话super();
}

所以编译时,A编译通过,但是编译B时会提示无法将A中的构造器应用到给定的类型,因为 super() 找不到A中的无参构造器

解决方法:
一、在A中加入无参的构造方法
二、在B中的所有构造方法的第一句话写上super(int);

无法将构造器应用到给定的类型
https://blog.csdn.net/songxueyu/article/details/14447201


IDEA安装lobbok插件

定位到 File > Settings > Plugins
点击 Browse repositories…
搜索 Lombok Plugin
点击 Install plugin
重启 IDEA


上一篇 Prometheus监控

下一篇 Apache-Commons-Pool 使用笔记

阅读
评论
1.5k
阅读预计6分钟
创建日期 2019-09-14
修改日期 2023-07-11
类别
标签

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论