lombok详解

349 阅读5分钟

一,lombok介绍

Lombok是使用java编写的一款开源类库。其主作用是使用注解来代替一些具有格式固定,没有过多技术含量的编码工作。使我们可以仅仅在代码中添加一个注解(annotation),就可以起到和编写一大段代码一样的作用。对于这些格式固定的的代码,IDE也提供了自动生成的功能,但是无论是自动生成还是纯手动写,这些代码在类中是实实在在的存在,有时候,看到一个类文件很长,其中却都是一些,没有任何技术含量的getter和setter方法。无疑会影响我们的代码阅读。而使用Lombok可以将这些“无用”的代码,通过相应的注解替换掉。

二,快速入门

  1. 导包

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    
  2. 在实体类使用注解

    @Data
    public class Result {
        private String code;
        private String msg;
        private Object data;
        public static Result success(Object data) {
            return new Result("200", "success", data);
        }
        public static Result error(String msg) {
            return new Result("500", msg, null);
        }
    }
    

三,Lombok的常用注解

3.1 @Getter和@Setter

  • 用法:标注在类/字段上

  • 作用:自动生成默认的get、set方法

  • 默认的get、set方法是public的,可以通过 @Setter(AccessLevel.PRIVATE) 来指定访问级别。

  • 如果在类上使用了@Getter和@Setter然后在属性上也使用了,那么属性上的优先级更高。

public class GetterSetterExample {
  @Getter 
  @Setter 
  private int age = 10;
 
  @Setter(AccessLevel.PROTECTED) 
  private String name;
      
}

3.2 @ToString

  • 用法:标注在类上
  • 作用:生成一个toString()的实现方法,可以通过 exclude 属性来排除不需要的字段,通过 includeFieldNames 属性来包含字段名称。
@ToString(exclude ={"id","name","pwd"})
public class LomBokDemo {

    private int id;
    private String name;
    private String pwd;

}

3.3 @EqualsAndHashCode

  • 用法:标注在类上
  • 作用:生成一个equals(Object other)和hashCode()的实现方法,可以通过 exclude 属性来排除不需要的字段。
    • 还有callSuper属性:控制是否调用父类equalshashCode 方法
      • callSuper = true:生成的 equalshashCode 方法会调用父类的相应方法。这通常用于在子类中比较时包含父类的状态。
      • callSuper = false:生成的 equalshashCode 方法不会调用父类的相应方法,只比较当前类的字段。这适用于那些不需要考虑父类状态的情况。
@ToString(exclude ={"id","name","pwd"})
@EqualsAndHashCode(callSuper = false,exclude ={"id","name","pwd"})
public class LomBokDemo {

    private int id;
    private String name;
    private String pwd;

}

3.4 生成构造方法

  • @NoArgsConstructor:生成无参构造函数。
  • @RequiredArgsConstructor:生成一个构造函数,其中包含所有 final 字段和标记为 @NonNull 的字段
  • @AllArgsConstructor:生成全参构造函数。

3.5 @Data

@ToString@EqualsAndHashCode@Getter@Setter 的组合,还会自动生成@RequiredArgsConstructor

3.6 @Builder

生成一个建造者类,并为这个类提供一个静态 builder() 方法。你可以通过这个 builder() 方法来创建一个 Builder 实例,并逐步设置字段的值,最后调用 build() 方法来创建对象。

import lombok.Builder;
@Builder
public class Person {
    private String name;
    private int age;
    private String address;
}
// 使用示例
public class Main {
    public static void main(String[] args) {
        Person person = Person.builder()
                              .name("John Doe")
                              .age(30)
                              .address("123 Main St")
                              .build();
        System.out.println(person);
    }
}

3.7 @Singular

搭配@Builder使用,如果类中包含集合类型字段(如 ListSetMap),你可以使用 @Singular 注解来自动生成添加元素的方法。

@Builder
public class LomBokDemo {
    private int age;
    private String name;
    private String pwd;
    @Singular("hobby")
    private List<String> hobby;
}
Person person = Person.builder()
                      .name("John Doe")
                      .age(30)
                      .hobby("Reading")
                      .hobby("Swimming")
                      .build();

3.8 @Log 系列

  • @Log@Log4j@Log4j2@Slf4j 等:自动为类添加日志对象。具体使用哪一种取决于所使用的日志框架,搭配log日志框架用于输出信息
@Slf4j
public class UserController {
    
    public Result getUserList(String name){
        log.info("name={}",name);
        return Result.success(userService.list());
    }
}

3.9 @NonNull

方法参数字段上使用,表示这个参数或字段不能为 null。它会在方法中生成检查 null 的代码。

  1. 方法参数

    • 当在方法参数上使用 @NonNull 注解时,Lombok 会在方法的开头生成 null 检查代码。如果参数为 null,会抛出 NullPointerException

      import lombok.NonNull;
      public class Example {
          
          public void printName(@NonNull String name) {
              System.out.println(name);
          }
      
          public static void main(String[] args) {
              Example example = new Example();
              example.printName("John Doe"); // 正常调用
              example.printName(null);       // 会抛出 NullPointerException
          }
      }
      
  2. 字段

    • 当在字段上使用 @NonNull 注解时,Lombok 会在类的构造函数中生成 null 检查代码,确保在对象创建时字段不会被赋值为 null

      import lombok.NonNull;
      import lombok.RequiredArgsConstructor;
      @RequiredArgsConstructor
      public class Person {
          @NonNull
          private final String name;
          private final int age;
      }
      
      // 使用示例
      public class Main {
          public static void main(String[] args) {
              Person person = new Person("John Doe", 30); // 正常
              Person personWithNull = new Person(null, 30); // 会抛出 NullPointerException
          }
      }
      

工作原理:

  • 方法参数:Lombok 在方法的开头生成 null 检查代码。

    public void printName(String name) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
        System.out.println(name);
    }
    
  • 字段:Lombok 在生成的构造函数中插入 null 检查代码。

    public Person(String name, int age) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
        this.name = name;
        this.age = age;
    }
    

注意事项:

  • @Builder 一起使用

    • @NonNull@Builder 一起使用时,Lombok 也会在 Builderbuild() 方法中进行 null 检查。
  • @RequiredArgsConstructor 一起使用

    • 在使用 @RequiredArgsConstructor 注解时,@NonNull 也会被用来确保构造函数中字段的非 null 约束。
  • 结合其他注解使用

    • @NonNull 注解通常与其他注解(如 @Data@Value)结合使用,以确保对象的字段在创建时具有良好的 null 安全性。

3.10 @Accessors

用于定制 Java 类中字段的访问器方法(getter 和 setter)。它允许你配置 getter 和 setter 方法的命名风格、链式调用等特性,从而使你的代码更加符合你的编码习惯和需求。

  1. fluent 属性

    fluent = true:生成流式(fluent)访问器方法,即不使用前缀(如 getset)来命名方法。

    • 默认情况下,Lombok 会生成类似 getFieldName()setFieldName() 的方法。

    • fluent 属性设置为 true 时,生成的方法将会是 fieldName()fieldName(value)

      @Getter
      @Setter
      @Accessors(fluent = true)
      public class Person {
          private String name;
          private int age;
      }
      
      // 使用示例
      public class Main {
          public static void main(String[] args) {
              Person person = new Person();
              person.name("John Doe").age(30);
              System.out.println(person.name()); // 使用流式访问器
          }
      }
      
  2. chain 属性:

    chain = true:使 setter 方法返回 this,以支持链式调用。这样,你可以在设置多个字段时将调用链式连接起来。

    @Getter
    @Setter
    @Accessors(chain = true)
    public class Person {
        private String name;
        private int age;
    }
    
    // 使用示例
    public class Main {
        public static void main(String[] args) {
            Person person = new Person()
                .name("John Doe")
                .age(30);
            System.out.println(person.getName());
        }
    }