Lombok(小辣椒)是一个 Java 库,它通过自动生成样板代码来简化 Java 代码的编写。它提供了一组注解,通过在源代码中添加这些注解,开发人员可以自动创建一些常见的样板代码,如 getter 和 setter 方法、构造函数、equals 和 hashCode 方法等。

使用 Lombok 可以显著减少代码量,提高开发效率,同时还能使代码更加清晰和易读。通过减少样板代码,Lombok 可以使开发人员更专注于业务逻辑的实现,而不必花费太多精力编写重复的代码。

下载

Maven

<dependency>
<groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
    <scope>provided</scope>
</dependency>

手动

官方网站:https://projectlombok.org/download 直链下载:https://projectlombok.org/downloads/lombok.jar

下载完成后导入到项目即可。

Maven 配置

原理

Lombok是一种插件化注解API,是通过添加注解来实现的,然后在javac进行编译的时候,进行处理。

Java的编译过程可以分成三个阶段:

  1. 所有源文件会被解析成语法树。
  2. 调用注解处理器。如果注解处理器产生了新的源文件,新文件也要进行编译。
  3. 最后,语法树会被分析并转化成类文件。

实际上在上述的第二阶段,会执行lombok.core.AnnotationProcessor,它所做的工作就是我们上面所说的,修改语法树。

使用

@Getter, @Setter

通过在类前添加 @Getter@Setter 可以在编译时自动生成一系列的参数封装函数。但在 IDEA 中若想调用需要安装 Lombok 插件(通常会自带)。

使用注解前:

public class Student {  
  
    private String name;  
    private int age;  
    private int sno;  
    public Student(int Sno, String name, int age) {  
        this.age = age;  
        this.name = name;  
        this.sno = Sno;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public void setSno(int sno) {  
        this.sno = sno;  
    }  
  
    public int getSno() {  
        return sno;  
    }  
  
    public int getAge() {  
        return age;  
    }  
  
    public String getName() {  
        return name;  
    }   
}

使用注解后:

@Getter  
@Setter  
public class Student {  
  
    private String name;  
    private int age;  
    private int sno;  
  
    public Student(int Sno, String name, int age) {  
        this.age = age;  
        this.name = name;  
        this.sno = Sno;  
    }  
}

但默认所有参数的set 和 get 方法都是 public。

可以通过设置注解属性来配置,比如全配置为 private:

@Getter(AccessLevel.PRIVATE)
@Setter  
public class Student {  
  
    private String name;  
    private int age;  
    private int sno;  
}

也可以在某个参数前单独加一个注解并设置属性:

@Getter
@Setter  
public class Student {  
  
    private String name;  
    @Getter(AccessLevel.PRIVATE)
    private int age;  
    private int sno;  
}

这样就只有 age 属性无法通过getter访问。

且默认是不会对finalstatic 的变量生成set方法,final 可以生成 get 方法。如果非要给 static 变量生成方法,也可以向上面单独设置权限一样,单独添加一个@Getter

@Accessors

@Accessors 可以给 @Getter@Setter 增加一些特性。

@Target({ElementType.TYPE, ElementType.FIELD})  // 同样支持单独变量设置
@Retention(RetentionPolicy.SOURCE)  
public @interface Accessors {  
    boolean fluent() default false;  
  
    boolean chain() default false;  
  
    boolean makeFinal() default false;  
  
    String[] prefix() default {};  
}

chain 属性默认为 false, 可以通过 @Accessors(chain = true) 设置为 true。效果是将生成的 get 方法返回一个原对象,这样可以支持链式调用:

Student student = new Student(123, "name", 123);  
student  
        .setSno(213)  
        .setAge(213);

fluent 属性则可以让生成的 set 方法名字中去掉 set, 只保留属性名:

Student student = new Student(123, "name", 123);  
student  
        .Sno(213)  
        .Age(213);

@ArgsConstructor

自动生成构造函数, 有两个版本, @NoArgsConstructor 是生成无参构造函数, @AllArgsConstructor 是生成代参构造函数,参数传入顺序跟声明顺序一致。

还有一个是 @RequiredArgsConstructor 是只会把 final 变量在构造函数中生成。

@ToString

@ToString 注解可以自动生成该类的 toString 方法,默认格式为 类名(属性名=值, 属性名=值...)

@Target({ElementType.TYPE})  
@Retention(RetentionPolicy.SOURCE)  
public @interface ToString {  
    boolean includeFieldNames() default true;  
  
    String[] exclude() default {};  
  
    String[] of() default {};  
  
    boolean callSuper() default false;  
  
    boolean doNotUseGetters() default false;  
  
    boolean onlyExplicitlyIncluded() default false;  
  
    @Target({ElementType.FIELD})  
    @Retention(RetentionPolicy.SOURCE)  
    public @interface Exclude {  
    }  
  
    @Target({ElementType.FIELD, ElementType.METHOD})  
    @Retention(RetentionPolicy.SOURCE)  
    public @interface Include {  
        int rank() default 0;  
  
        String name() default "";  
    }  
}

其中也可以配置很多属性:

includeFieldNames

默认开启时会输出字段对应的名字:

Student(name=name, age=123, sno=1213)

@ToString(includeFieldNames = false)关闭后就会省略字段名字:

Student(name, 123, 1213)

exclude

默认为空,表示没有不输出的变量。 @ToString(exclude = {"name", "sno"})可以设置多个变量不输出:

Student(age=123)

of

exclude 使用方法一样,但是刚好相反,是只保留选择的,其他的省去。

callSuper

会自动在第一项增加调用父类的 toString() 方法:

Student(super=Student@4e50df2e, name=name, age=123, sno=1213)

doNotUseGetters

Lombok 的 toString 方法在访问某个变量的值时, 如果其有 Getter 方法会自动调用,而非直接访问。

@ToString(doNotUseGetters = true) 后,访问变量值时就不会再调用 Getter 方法。

Include

可以通过单独设置某个变量的位置和别名: @ToString.Include(name = "年龄")

Student(name=name, 年龄=123, sno=1213)

@EqualsAndHashCode

自动生成当前类的 equalshashCode 方法。其中 equals 方法默认不会比较父类的属性,因此需要设置 @EqualsAndHashCode(callSuper = true) 才会在 equals 先调用父类的 equals 方法来比较。

@Data

@Data:该注解包含了 @Getter@Setter@ToString@EqualsAndHashCode@RequiredArgsConstructor 的功能,是一个快捷注解,常用于简化 POJO 类的定义。

@Data 没有更多的控制属性,无法像@EqualsAndHashCode 一样设置调用父类 equals 方法,因此不建议使用的类含有继承关系。

@SneakyThrows

注解在方法中时, 会自动对会报错的部分进行 try-catch 包围。

编译前:

@SneakyThrows  
public static void main(String[] args) {  
    Student student = new Student(1213, "name", 123);  
    System.out.println(student);  
    InputStream inputStream = new FileInputStream("1213");   
}

编译后:

public static void main(String[] args) {  
    try {  
        Student student = new Student(1213, "name", 123);  
        System.out.println(student);  
        new FileInputStream("1213");  
    } catch (Throwable var3) {  
        throw var3;  
    }  
}

@Cleanup

只能定义在变量前,会在合适的时候自动调用该变量的 close() 方法,通常用于 IO 流。

配合 @SneakyThrows 可以直接实现 try-with-resources 的功能。

@SneakyThrows  
public static void main(String[] args) {  
    Student student = new Student(1213, "name", 123);  
    System.out.println(student);  
    @Cleanup  
    InputStream inputStream = new FileInputStream("1213");  
}

编译后:

try {  
    Student student = new Student(1213, "name", 123);  
    System.out.println(student);  
    InputStream inputStream = new FileInputStream("1213");  
    if (Collections.singletonList(inputStream).get(0) != null) {  
        inputStream.close();  
    }  
} catch (Throwable var3) {  
    throw var3;  
}
  1. @Builder:自动生成建造者模式相关的代码,简化对象的创建过程。
  2. @Slf4j:自动为类生成一个名为 log 的日志记录器,方便在代码中进行日志输出。

@Log

自动为该类创建 Logger 对象,等价于:

Logger logger = Logger.getLogger(myUserDao.class.getName());

之后使用 log 来调用即可:

@Log
public class Main {
    public static void main(String[] args) {
        System.out.println("自动生成的Logger名称:"+log.getName());
        log.info("我是日志信息");
    }
}

可以加上 @Log(topic = "String") 来更改 Logger 名字。