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 小时前
验证码机制
前端·后端
超爱吃士力架4 小时前
邀请逻辑
java·linux·后端
AskHarries6 小时前
Spring Cloud OpenFeign快速入门demo
spring boot·后端
isolusion7 小时前
Springboot的创建方式
java·spring boot·后端
zjw_rp7 小时前
Spring-AOP
java·后端·spring·spring-aop
TodoCoder8 小时前
【编程思想】CopyOnWrite是如何解决高并发场景中的读写瓶颈?
java·后端·面试
凌虚9 小时前
Kubernetes APF(API 优先级和公平调度)简介
后端·程序员·kubernetes
机器之心9 小时前
图学习新突破:一个统一框架连接空域和频域
人工智能·后端
.生产的驴10 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
顽疲10 小时前
springboot vue 会员收银系统 含源码 开发流程
vue.js·spring boot·后端