官网:https://www.projectlombok.org
github源码地址:https://github.com/rzwitserloot/lombok
Lombok是一个Java库,它能通过注解的方式自动生成一些Java代码,从而减少代码冗余。以下是一些Lombok常用的注解:
-
@Data
- 功能:这是一个组合注解,它相当于同时使用了
@Getter
、@Setter
、@ToString
、@EqualsAndHashCode
和@RequiredArgsConstructor
(如果没有无参构造函数的话)。例如,对于一个简单的User
类:
import lombok.Data; @Data class User {private String name;private int age; }
- 效果:Lombok会自动为
name
和age
生成getter
和setter
方法。同时,它也会生成一个toString
方法,用于方便地打印对象的属性值;一个equals
和hashCode
方法,用于比较对象是否相等和生成哈希码;如果没有定义其他构造函数,还会生成一个包含所有final
属性或者有@NonNull
注解的属性作为参数的构造函数。
- 功能:这是一个组合注解,它相当于同时使用了
-
@Value
- 功能:主要用于创建不可变(immutable)的值对象。值对象是一种设计模式,这种对象在创建之后其状态不能被修改,所有的属性通常是final的。例如,对于一个简单的
Point
类:
import lombok.Value; @Value public class Point {final int x;final int y; }
- 效果:Lombok会自动为
x
和y
生成getter
方法。同时,它也会生成一个toString
方法,用于方便地打印对象的属性值;一个equals
和hashCode
方法,用于比较对象是否相等和生成哈希码。通常和@Builder
注解联合使用,Point point = Point.Builder().x(1).y(1).build();
- 功能:主要用于创建不可变(immutable)的值对象。值对象是一种设计模式,这种对象在创建之后其状态不能被修改,所有的属性通常是final的。例如,对于一个简单的
-
@Getter和@Setter
- 功能:
@Getter
用于为类中的属性自动生成get
方法。例如:
import lombok.Getter; class Book {@Getterprivate String title; }
@Setter
用于为类中的属性自动生成set
方法。例如:
import lombok.Setter; class Laptop {@Setterprivate double price; }
- 效果:使用
@Getter
后,就可以通过book.getTitle()
来获取title
属性的值;使用@Setter
后,可以通过laptop.setPrice(1000.0)
来设置price
属性的值。这两个注解可以单独使用,也可以一起使用,具体取决于是否需要读写属性。
- 功能:
-
@ToString
- 功能:用于自动生成
toString
方法。例如:
import lombok.ToString; @ToString class Student {private String studentId;private String major; }
- 效果:当需要打印
Student
对象时,会自动输出对象的属性值,类似于Student(studentId=xxx, major=xxx)
的格式。可以通过@ToString(exclude = "studentId")
这样的方式来排除某些属性,不将它们包含在toString
输出的内容中。
- 功能:用于自动生成
-
@EqualsAndHashCode
- 功能:自动生成
equals
和hashCode
方法。例如:
import lombok.EqualsAndHashCode; @EqualsAndHashCode class Employee {private String employeeId;private String department; }
- 效果:当需要比较两个
Employee
对象是否相等或者将它们作为键放入HashSet
或HashMap
等基于哈希的集合中时,这些自动生成的方法会根据对象的属性来进行比较和生成哈希码。同样,可以通过@EqualsAndHashCode(exclude = "department")
来指定排除某些属性参与equals
和hashCode
的计算。
- 功能:自动生成
-
@NoArgsConstructor
- 功能:生成一个无参构造函数。例如:
import lombok.NoArgsConstructor; @NoArgsConstructor class Product {private String productName;private double price; }
- 效果:这样就可以通过
new Product()
来创建一个Product
对象,在一些场景下,比如反序列化或者通过反射创建对象时,无参构造函数是很有用的。
-
@AllArgsConstructor
- 功能:生成一个包含所有属性的构造函数。例如:
import lombok.AllArgsConstructor; @AllArgsConstructor class Order {private String orderId;private String customerName;private double totalAmount; }
- 效果:可以通过
new Order("001", "John", 100.0)
这样的方式使用包含所有属性的构造函数来创建Order
对象。
-
@RequiredArgsConstructor
- 功能:生成一个包含
final
属性或者有@NonNull
注解的属性作为参数的构造函数。例如:
import lombok.RequiredArgsConstructor; import lombok.NonNull; @RequiredArgsConstructor class Vehicle {@NonNullprivate String vehicleId;private final String brand; }
- 效果:Lombok会生成一个构造函数,其中
vehicleId
和brand
作为参数,因为vehicleId
被@NonNull
注解修饰,brand
是final
的。这样可以确保这些重要属性在对象创建时被初始化。
- 功能:生成一个包含
-
@Builder
- 功能:提供一种简洁的方式来创建对象,采用建造者(Builder)模式。例如:
import lombok.Builder; @Builder class House {private String address;private int numberOfRooms; }
- 效果:可以使用
House house = House.builder().address("123 Main St").numberOfRooms(4).build();
这样的方式来构建House
对象,这种方式在创建对象时参数较多或者对象属性有一些默认值和可选值的情况下非常方便。
-
@Log、@Slf4j等日志相关注解
- 功能:这些注解用于自动生成日志对象,方便在类中进行日志记录。例如
@Slf4j
:
import lombok.extern.slf4j.Slf4j; @Slf4j class MyService {public void doSomething() {log.info("执行了doSomething方法");} }
- 效果:Lombok会自动为
MyService
类生成一个名为log
的SLF4J
日志对象,通过这个日志对象就可以方便地在类的方法中记录各种级别的日志信息,如debug
、info
、warn
、error
等。不同的日志相关注解(如@Log
、@Log4j
等)对应不同的日志框架,但它们的作用都是类似的,用于简化日志对象的创建过程。
- 功能:这些注解用于自动生成日志对象,方便在类中进行日志记录。例如
-
@UtilityClass
- 功能:构造函数私有化;提供静态方法和静态变量访问方式。
import lombok.experimental.UtilityClass; @UtilityClass public class StringUtils {public static boolean isEmpty(String str) {return str == null || str.length() == 0;} }
- 效果:Lombok会自动将
StringUtils
类的构造函数设为私有;使用@UtilityClass注解后,这些静态成员可以直接通过类名来访问,如StringUtils.isEmpty(“”),这符合工具类的使用习惯,即提供一组方便调用的实用功能,而不需要创建类的实例。
-
@Cleanup
- 功能:主要用于自动资源管理。在 Java 中,许多资源(如文件流、数据库连接、网络连接等)在使用完后需要手动关闭,以防止资源泄漏。@Cleanup注解可以简化这个过程。
在处理文件读取时,传统的代码可能如下:
import java.io.File; import java.io.FileReader; import java.io.IOException; public class FileReadExample {public static void main(String[] args) {FileReader reader = null;try {File file = new File("example.txt");reader = new FileReader(file);char[] buffer = new char[(int) file.length()];reader.read(buffer);System.out.println(buffer);} catch (IOException e) {e.printStackTrace();} finally {if (reader!= null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}} }
- 使用`@Cleanup`注解后,代码可以简化为:```javaimport lombok.Cleanup;import java.io.File;import java.io.FileReader;import java.io.IOException;public class FileReadExampleWithCleanup {public static void main(String[] args) {try {File file = new File("example.txt");@Cleanup FileReader reader = new FileReader(file);char[] buffer = new char[(int) file.length()];reader.read(buffer);System.out.println(buffer);} catch (IOException e) {e.printStackTrace();}}}
- 效果:
Lombok
在编译阶段会在使用@Cleanup
注解的变量所在的代码块结束时,插入相应的资源释放代码(通常是调用资源的close()
方法)。它会通过反射等方式来确定资源的关闭方法。对于大多数遵循Java
标准的资源(如实现了java.io.Closeable
或java.lang.AutoCloseable
接口的资源),@Cleanup
都能很好地工作。
- 功能:主要用于自动资源管理。在 Java 中,许多资源(如文件流、数据库连接、网络连接等)在使用完后需要手动关闭,以防止资源泄漏。@Cleanup注解可以简化这个过程。
-
@Singular
- 功能:主要用于和集合类型的属性一起使用,特别是在生成构建器(Builder)模式相关代码的时候。它提供了一种方便的方式来添加单个元素到集合属性中,而不是一次性设置整个集合。
import lombok.Builder; import lombok.Singular; import java.util.List; @Builder public class Order {@Singular("product")private List<Product> products; } class Product {private String name;private double price;// 构造函数、getter和setter等方法省略 }Order order = Order.builder().product(new Product("Book", 10.0)).product(new Product("Pen", 2.0)).build();
- 效果:Lombok会确保生成的构建器代码在内部正确地处理集合的添加操作,避免了需要先构建整个商品列表然后再设置给Order对象的繁琐过程。
- 注意事项:
@Singular
主要用于集合类型的属性,如List
、Set
、Map
等。如果应用到非集合类型的属性上,Lombok 可能会产生编译错误或者不符合预期的行为;在使用@Singular
注解时,指定的方法名称(如上述示例中的product
)如果与类中的其他方法名称冲突,可能会导致编译问题或者运行时的异常行为,因此,在命名时需要注意避免冲突。
-
@Delegate
- 功能:用于实现委托(delegation)模式。委托模式是一种设计模式,它允许一个对象将一些职责委托给另一个对象来处理。
class Person {private String name;private int age;public String getName() {return name;}public int getAge() {return age;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;} }// 现在创建`Employee`类并使用`@Delegate`注解: import lombok.Delegate; class Employee {@Delegateprivate Person person;public Employee(Person person) {this.person = person;} }Person person = new Person(); person.setName("John"); person.setAge(30); Employee employee = new Employee(person); System.out.println(employee.getName()); System.out.println(employee.getAge()); employee.setName("Jane"); System.out.println(person.getName());
- 效果:
Employee
类通过@Delegate
注解委托Person
类来处理getName
、getAge
、setName
和setAge
等方法。就好像Employee
类自己拥有这些方法一样,实际上是将这些方法的调用委托给了内部的Person
对象来处理。
-
@SneakyThrows
- 功能:将方法中可能抛出的已检查异常(Checked Exceptions)转换为未检查异常(Unchecked Exceptions)。
import java.io.File; import java.io.FileInputStream; public class FileReadExample {public static void main(String[] args) {try {File file = new File("example.txt");FileInputStream fis = new FileInputStream(file);// 进一步的文件读取操作} catch (Exception e) {e.printStackTrace();}} }// 使用`@SneakyThrows`后的示例: import lombok.SneakyThrows; import java.io.File; import java.io.FileInputStream; public class FileReadExampleWithSneakyThrows {@SneakyThrowspublic static void main(String[] args) {File file = new File("example.txt");FileInputStream fis = new FileInputStream(file);// 进一步的文件读取操作} }
- 效果:在使用
@SneakyThrows
注解的方法中,如果出现了已检查异常,Lombok 会在编译阶段将这个已检查异常包装成一个RuntimeException
(未检查异常)。这样就不需要在方法签名中声明抛出异常,也不需要在方法内部显式地使用try - catch
块来处理这个异常,从一定程度上简化了代码。不过,这也意味着异常的处理被推迟到了调用栈的上层,可能会导致异常信息在传播过程中丢失部分细节或者使得异常的处理不够及时和精确。