一、概述
Lombok 是一种Java 实用工具,可以帮助开发人员消除冗长的重复代码,尤其是对于简单的 Java 对象。它在代码编译阶段就会自动生成相应的代码,所以对性能没有任何影响。
Maven 项目中引入 Lombok:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> <scope>provided</scope> </dependency>
然后在 IDE(IDEA、Eclipse 等)中安装 Lombok 插件。
二、特性
类型 | 作用 | 备注 |
val |
定义 final 本地局部变量 |
必须要初始化 |
var |
定义本地局部变量 | 必须要初始化 |
@NonNull |
定义非空检查 | |
@Cleanup |
自动关闭资源 | |
@Getter/@Setter |
定义 Getter/Setter 方法 | |
@ToString |
定义 toString 方法 |
|
@EqualsAndHashCode |
定义 hashCode 和 equals 方法 |
|
@NoArgsConstructor |
定义无参构造方法 | |
@RequiredArgsConstructor |
定义非空参数构造方法 | |
@AllArgsConstructor |
定义全参构造方法 | |
@Data |
包含 @ToString 、@Getter 、@Setter 等常用注解 |
|
@Builder |
定义构造器 | |
@SneakyThrows |
定义异常捕获,省略 throws 操作 |
|
@Synchronized |
定义同步锁 | |
@Log |
定义日志变量,支持 @Log4j 、Slf4j 等 |
三、实践
val
使用 val
可以定义一个本地局部变量,而不用指定该变量的类型,默认会使用 final
修饰,所以必须初始化。
public class Example { // Lombok public void lombok() { val str = "CodeArtist"; val year = 2021; System.out.println(str); System.out.println(year); } // 原生Java public void example() { final String str = "CodeArtist"; final int year = 2021; System.out.println(str); System.out.println(year); } }
var
var
和 val
功能一样,定义一个本地局部变量,只不过没有用 final
修饰,可以二次赋值,在使用的时候也需要初始化。
public class Example { // Lombok public void lombok() { var str = "CodeArtist"; var year = 2021; System.out.println(str); System.out.println(year); } // 原生Java public void example() { String str = "CodeArtist"; int year = 2021; System.out.println(str); System.out.println(year); } }
@NonNull
@NonNull
可以作用在构造方法或其他方法的参数上,会在方法开头对参数添加一个非空检验,为空时抛出空指针异常。
public class Example { // Lombok public void lombok(@NonNull String name) { System.out.println(name); } // 原生Java public void example(String name) { if (name == null) { throw new NullPointerException("name is marked non-null but is null"); } else { System.out.println(name); } } }
@Cleanup
在定义一个资源前面添加 @Cleanup
,可以使用完后自动调用 close()
方法来关闭资源。
public class Example { // Lombok public void lombok() throws Exception { @Cleanup InputStream in = new FileInputStream("path"); byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; } } // 原生Java public void example() throws Exception { InputStream in = new FileInputStream("path"); try { byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; } } finally { if (in != null) { in.close(); } } } }
@Getter/@Setter
使用 @Getter/@Setter
注解来生成类字段的 Getter 和 Setter 方法,它们也可以单独作用在字段上,来对生成某个字段 Getter 和 Setter 方法。
// Lombok @Getter @Setter public class Example { private int age; private String name; } // 原生Java public class Example { private int age; private String name; public int getAge() { return this.age; } public String getName() { return this.name; } public void setAge(int age) { this.age = age; } public void setName(String name) { this.name = name; } }
@ToString
使用 @ToString
可以对字段生成 toString
方法,在打印日志的时候可以输出对象的字段值,也可以使用 @ToString.Exclude
注解来指定哪个字段不打印。
// Lombok @ToString public class Example { private int age; private String name; } // 原生Java public class Example { private int age; private String name; public String toString() { return "Example(age=" + this.age + ", name=" + this.name + ")"; } }
@EqualsAndHashCode
使用 @EqualsAndHashCode
生成对象的 equals()
和 hashCode()
方法,也可以使用 @EqualsAndHashCode.Exclude
注解来不包含某个字段。
// Lombok @EqualsAndHashCode public class Example { private int age; private String name; } // 原生Java public class Example { private int age; private String name; public boolean equals(final Object o) { // 省略 return true; } public int hashCode() { // 省略 return 0; } }
@ToString
和 @EqualsAndHashCode
如果类中有继承的情况,可以在注解中定义 callSuper
来生成包含调用父类方法的代码。
@NoArgsConstructor
使用 @NoArgsConstructor
来生成无参构造方法。
// Lombok @NoArgsConstructor public class Example { private int age; private String name; } // 原生Java public class Example { private int age; private String name; public Example() { } }
@RequiredArgsConstructor
使用 @RequiredArgsConstructor
来生成含有必须需要初始化参数的参构造方法,比如 final
修饰的字段。
// Lombok @RequiredArgsConstructor public class Example { private final String name; private int age; } // 原生Java public class Example { private int age; private final String name; public Example(String name) { this.name = name; } }
@AllArgsConstructor
使用 @AllArgsConstructor
来生成含有所有参数的构造方法。
// Lombok @AllArgsConstructor public class Example { private String name; private int age; } // 原生Java public class Example { private String name; private int age; public Example(String name, int age) { this.name = name; this.age = age; } }
生成构造方法的注解都可以通过
access
属性来指定构造方法的访问权限。
@Data
@Data
注解是定义实体类最常用的注解,它将常用的注解整合成一个,功能包括:
@Getter
@Setter
@ToString
@EqualsAndHashCode
@RequiredArgsConstructor
// Lombok @Data public class Example { private String name; private int age; } @Getter @Setter @ToString @EqualsAndHashCode @RequiredArgsConstructor public class Example { private String name; private int age; }
@Builder
@Builder
注解可以生成一个内部类来使用构造器设计模式来给 Java 对象赋值。
// Lombok @Builder public class Example { private String name; private int age; } // 原生Java public class Example { private String name; private int age; Example(String name, int age) { this.name = name; this.age = age; } public static ExampleBuilder builder() { return new ExampleBuilder(); } public static class ExampleBuilder { private String name; private int age; ExampleBuilder() { } public ExampleBuilder name(String name) { this.name = name; return this; } public ExampleBuilder age(int age) { this.age = age; return this; } public Example build() { return new Example(name, age); } public String toString() { return "Example.ExampleBuilder(name=" + this.name + ", age=" + this.age + ")"; } } }
@SneakyThrows
@SneakyThrows
可以对编译时校验的异常进行捕获然后处理。
public class Example { // Lombok @SneakyThrows private void lombok() { TimeUnit.MINUTES.sleep(1); } // 原生Java private void example() { try { TimeUnit.MINUTES.sleep(1L); } catch (Throwable e) { throw Lombok.sneakyThrow(e); } } }
@Synchronized
@Synchronized
可以给方法内部在代码加上 synchronized
同步锁。
public class Example { private final Object $lock = new Object[0]; // Lombok @Synchronized private void lombok() { System.out.println("CodeArtist"); } // 原生Java private void example() { synchronized (this.$lock) { System.out.println("CodeArtist"); } } }
@Log
@Log
可以在类中定义一个日志变量,它包括生成一系列日志框架的变量的注解,常用的有:
@Log
@Log4j
Slf4j
// Lombok @Slf4j public class Example { } // 原生Java public class Example { private static final Logger log = org.slf4j.LoggerFactory.getLogger(Example.class); }