Lombok 简单使用

参考

blog.csdn.net/ThinkWon/ar...

www.baeldung.com/intro-to-pr...

projectlombok.org/features/

介绍

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

相关推荐
攸攸太上2 分钟前
JMeter学习
java·后端·学习·jmeter·微服务
Kenny.志5 分钟前
2、Spring Boot 3.x 集成 Feign
java·spring boot·后端
sky丶Mamba22 分钟前
Spring Boot中获取application.yml中属性的几种方式
java·spring boot·后端
千里码aicood1 小时前
【2025】springboot教学评价管理系统(源码+文档+调试+答疑)
java·spring boot·后端·教学管理系统
程序员-珍2 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
liuxin334455662 小时前
教育技术革新:SpringBoot在线教育系统开发
数据库·spring boot·后端
数字扫地僧2 小时前
HBase与Hive、Spark的集成应用案例
后端
架构师吕师傅2 小时前
性能优化实战(三):缓存为王-面向缓存的设计
后端·微服务·架构
bug菌3 小时前
Java GUI编程进阶:多线程与并发处理的实战指南
java·后端·java ee
夜月行者4 小时前
如何使用ssm实现基于SSM的宠物服务平台的设计与实现+vue
java·后端·ssm