参考
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 方法。