参考
www.baeldung.com/intro-to-pr...
介绍
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java. Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
添加依赖:
xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
在 idea 中需要确保安装了 Lombok 插件。
基本用法
生成 get 和 set 方法
使用 Lombok 的 @Getter 和 @Setter 方法,可以自动为我们生成 get 和 set 方法。
less
import lombok.Getter;
import lombok.Setter;
public class Person {
@Getter
@Setter
private String name;
private int age;
private String address;
}
编译后的代码:
arduino
public class Person {
private String name;
private int age;
private String address;
public Person() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
toString 方法
使用 Lombok 中的 @ToString 方法会自动为我们生成 toString 方法。
less
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@ToString
public class Person {
@Getter
@Setter
private String name;
private int age;
private String address;
}
编译后的代码:
typescript
public class Person {
private String name;
private int age;
private String address;
public Person() {
}
public String toString() {
return "Person(name=" + this.getName() + ", age=" + this.age + ", address=" + this.address + ")";
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
equals 和 hashCode 方法
@EqualsAndHashCode 注解会同时生成 equals 方法和 hashCode 方法。
typescript
@EqualsAndHashCode
public class Address {
private String street;
private String city;
private String state;
private String postalCode;
}
编译后的代码:
kotlin
public class Address {
private String street;
private String city;
private String state;
private String postalCode;
public Address() {
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Address)) {
return false;
} else {
Address other = (Address)o;
if (!other.canEqual(this)) {
return false;
} else {
label59: {
Object this$street = this.street;
Object other$street = other.street;
if (this$street == null) {
if (other$street == null) {
break label59;
}
} else if (this$street.equals(other$street)) {
break label59;
}
return false;
}
Object this$city = this.city;
Object other$city = other.city;
if (this$city == null) {
if (other$city != null) {
return false;
}
} else if (!this$city.equals(other$city)) {
return false;
}
Object this$state = this.state;
Object other$state = other.state;
if (this$state == null) {
if (other$state != null) {
return false;
}
} else if (!this$state.equals(other$state)) {
return false;
}
Object this$postalCode = this.postalCode;
Object other$postalCode = other.postalCode;
if (this$postalCode == null) {
if (other$postalCode != null) {
return false;
}
} else if (!this$postalCode.equals(other$postalCode)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof Address;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $street = this.street;
result = result * 59 + ($street == null ? 43 : $street.hashCode());
Object $city = this.city;
result = result * 59 + ($city == null ? 43 : $city.hashCode());
Object $state = this.state;
result = result * 59 + ($state == null ? 43 : $state.hashCode());
Object $postalCode = this.postalCode;
result = result * 59 + ($postalCode == null ? 43 : $postalCode.hashCode());
return result;
}
}
构造方法
@NoArgsConstructor:生成无参构造方法。 @AllArgsConstructor:生成所有字段的构造方法。 @RequiredArgsConstructor:当你在一个类中使用 @RequiredArgsConstructor 注解时,Lombok 会自动帮你生成一个构造函数,该构造函数仅包含类中定义的 final 字段或者被 @NonNull 注解标记的字段。
arduino
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private int id;
private String name;
private String department;
private double salary;
}
编译后的 java 代码:
arduino
public class Employee {
private int id;
private String name;
private String department;
private double salary;
public Employee(int id, String name, String department, double salary) {
this.id = id;
this.name = name;
this.department = department;
this.salary = salary;
}
public Employee() {
}
}
java
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.List;
@RequiredArgsConstructor
public class Order {
private final int orderId;
private List<String> products;
@NonNull
private double totalPrice;
}
编译后的代码:
java
import com.jxd.bug.Product;
import java.util.List;
import lombok.NonNull;
public class Order {
private final int orderId;
private List<Product> products;
private @NonNull double totalPrice;
public Order(int orderId, @NonNull double totalPrice) {
this.orderId = orderId;
this.totalPrice = totalPrice;
}
}
高级用法
日志
lombok 提供了 @Slf4j、@Log、@CommonsLog、@Log4j、@Log4j2、@XSlf4j、@Slf4j 这些日志注解来对应不同的日志框架。
typescript
import lombok.extern.slf4j.Slf4j;
/**
* @author jxd
* {@code @date} 2024/3/26 21:47
*/
@Slf4j
public class Log {
public static void main(String[] args) {
log.info("@Slf4j annotation");
}
}
编译后的代码:
arduino
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Log {
private static final Logger log = LoggerFactory.getLogger(Log.class);
public Log() {
}
public static void main(String[] args) {
log.info("@Slf4j annotation");
}
}
@Data 注解
相当于这些注解的一个聚合:
- @ToString
- @EqualsAndHashCode
- @Getter
- @Setter
- @RequiredArgsConstructor
@Builder 注解
@Builder 注解会自动为我们生成 bean 对应的 Builder,有了这个 Builder,就可以使用通过链式调用的方式来构建对象(建造者模式)。
typescript
import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class Customer {
private String customerId;
private String name;
private String email;
private String phoneNumber;
}
编译后的代码:
kotlin
public class Customer {
private String customerId;
private String name;
private String email;
private String phoneNumber;
Customer(String customerId, String name, String email, String phoneNumber) {
this.customerId = customerId;
this.name = name;
this.email = email;
this.phoneNumber = phoneNumber;
}
public static CustomerBuilder builder() {
return new CustomerBuilder();
}
public String toString() {
return "Customer(customerId=" + this.customerId + ", name=" + this.name + ", email=" + this.email + ", phoneNumber=" + this.phoneNumber + ")";
}
public static class CustomerBuilder {
private String customerId;
private String name;
private String email;
private String phoneNumber;
CustomerBuilder() {
}
public CustomerBuilder customerId(String customerId) {
this.customerId = customerId;
return this;
}
public CustomerBuilder name(String name) {
this.name = name;
return this;
}
public CustomerBuilder email(String email) {
this.email = email;
return this;
}
public CustomerBuilder phoneNumber(String phoneNumberCu
使用 Builder 去构造 Customer 对象:
java
import org.junit.jupiter.api.Test;
/**
* @author jxd
* {@code @date} 2024/3/26 22:05
*/
public class UseCustomer {
@Test
public void useBuilder() {
final Customer tom = new Customer.CustomerBuilder()
.email("example.163.com")
.customerId("1")
.phoneNumber("1121")
.name("tom")
.build();
System.out.println(tom);
}
}
懒加载
@Getter(lazy = true)
常见坑
boolean 类型的字段
vbnet
@Data
public class Product {
private String name;
private double price;
private String description;
/**
* boolean 类型的字段会生成 is 方法,而不会生成 get 方法
*/
private boolean sellOut;
}
编译后的代码:
kotlin
public class Product {
private String name;
private double price;
private String description;
private boolean sellOut;
public Product() {
}
public String getName() {
return this.name;
}
public double getPrice() {
return this.price;
}
public String getDescription() {
return this.description;
}
public boolean isSellOut() {
return this.sellOut;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(double price) {
this.price = price;
}
public void setDescription(String description) {
this.description = description;
}
public void setSellOut(boolean sellOut) {
this.sellOut = sellOut;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Product)) {
return false;
} else {
Product other = (Product)o;
if (!other.canEqual(this)) {
return false;
} else if (Double.compare(this.getPrice(), other.getPrice()) != 0) {
return false;
} else if (this.isSellOut() != other.isSellOut()) {
return false;
} else {
label40: {
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name == null) {
break label40;
}
} else if (this$name.equals(other$name)) {
break label40;
}
return false;
}
Object this$description = this.getDescription();
Object other$description = other.getDescription();
if (this$description == null) {
if (other$description != null) {
return false;
}
} else if (!this$description.equals(other$description)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof Product;
}
public int hashCode() {
int PRIME = true;
int result = 1;
long $price = Double.doubleToLongBits(this.getPrice());
result = result * 59 + (int)($price >>> 32 ^ $price);
result = result * 59 + (this.isSellOut() ? 79 : 97);
Object $name = this.getName();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
Object $description = this.getDescription();
result = result * 59 + ($description == null ? 43 : $description.hashCode());
return result;
}
public String toString() {
return "Product(name=" + this.getName() + ", price=" + this.getPrice() + ", description=" + this.getDescription() + ", sellOut=" + this.isSellOut() + ")";
}
sellOut 字段是 Boolean 类型,没有生成它的 get 方法,生成了一个 isSellOut 方法。
名称不规则字段的 get set 方法名问题
arduino
import lombok.Data;
@Data
public class Book {
private String isbn;
private String title;
private String aAuthor;
private int pageCount;
private double price;
}
编译后的代码:
arduino
public class Book {
private String isbn;
private String title;
private String aAuthor;
private int pageCount;
private double price;
// 省略无关代码
public String getAAuthor() {
return this.aAuthor;
}
public void setAAuthor(String aAuthor) {
this.aAuthor = aAuthor;
}
}
使用 idea 生成的 get 和 set 方法却是:
typescript
public String getaAuthor() {
return aAuthor;
}
public void setaAuthor(String aAuthor) {
this.aAuthor = aAuthor;
}
因为这个原因,导致 lombok 和 mybatis 一起使用时有时就会产生问题。
生成的 equals 方法
使用 @Data 注解生成的 equals 方法,默认只判断了当前类的属性是否相等,而忽略了父类的属性,从而使两个明显不相等的对象通过 equals 判断为相等。 解决方式就是使用 @EnqualsAndHashCode 注解并显示指定 canSuper=true,这样就会调用父类的 equals 方法。
scala
import lombok.Data;
/**
* @author jxd
* {@code @date} 2024/3/26 22:34
*/
@Data
public class PictureBook extends Book {
private Integer pictureNm;
}
上面定义了一个 PictureBook 类,使用了 @Data 注解,如果调用 PictureBook 的 equals 方法,默认只会根据 pictureNm 来判断两个 PictureBook 对象是否相等。 需要添加如下的注解,才会调用父类的 equals 方法。