Lombok详细使用说明及其注意事项和Lombok注解详解

2023-12-24 11:45:37

1. 简介

官网

? 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.

翻译

? Project Lombok 是一个 Java 库,它会自动插入编辑器和构建工具,为您的 Java 增添趣味。
永远不要再写另一个 getter 或 equals 方法,使用一个注释,您的类有一个功能齐全的构建器,自动化您的日志记录变量等等。

Lombok 的官方网站为 https://projectlombok.org/ 。

Lombok 的优点包括:

  • 简化 Java 代码,减少样板式代码,提高开发效率;
  • Lombok 通过注解为 Java 类生成代码,在不修改源代码的前提下,为类增加属性和方法,并且这些方法和属性的可见性可以适当控制;
  • Lombok 提供了一组非常强大的注解,包括:@Getter、@Setter、@ToString、@EqualsAndHashCode、@Data、@Builder、@Slf4j 等。

Lombok 的缺点是它对编译器的支持不够友好,有时候可能会导致编译器的报错、警告和 IDE 的智能提示问题。

总之,Lombok 是一款非常流行的 Java 工具类库,可以极大地提高 Java 开发效率和代码质量。

2.使用

2.1 依赖包

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
             <version>1.18.20</version>
			<scope>provided</scope>
		</dependency>

3.注解

3.1 @Data

? @Data 是 Lombok 提供的注解之一,可以自动为类中的所有属性生成 getter、setter、equals、hashCode、toString 等方法,避免了开发人员重复编写这些方法的繁琐过程,提高了代码的简洁性和可读性。

? 使用 @Data 注解只需在类上添加 @Data 注解即可,无需再手动编写 getter、setter、equals、hashCode、toString 等方法。

? 如为final属性,则不会为该属性生成setter方法。

举例

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
}

上述代码中,使用 @Data 注解为 User 类自动创建了 getter、setter、equals、hashCode、toString 等方法。在使用时,只需要像普通类一样使用即可,例如:

User user = new User();
user.setId(1L);
user.setName("Tom");
user.setAge(20);

3.2 @AllArgsConstructor

@AllArgsConstructor 是 Lombok 提供的注解之一,可以自动生成带有所有参数的构造方法。

使用 @AllArgsConstructor 注解只需要在类上添加该注解即可,无需再手动编写带有所有参数的构造方法。

举例

@Data
@AllArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
}

上述代码中,使用 @AllArgsConstructor 注解为 User 类自动创建了一个带有所有参数的构造方法,可以通过该构造方法同时初始化所有属性。例如:

User user = new User(1L, "Tom", 20);
	

3.3 @NoArgsConstructor

@NoArgsConstructor 是 Lombok 提供的注解之一,可以自动生成无参构造方法。

如果在类中不手动添加构造函数,则编译器会自动生成一个无参构造方法。但是,如果在类中手动添加了其他构造方法,则编译器就不会再去自动生成无参构造方法。这时可以使用 @NoArgsConstructor 注解来自动生成无参构造方法。

举例

@Data
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
}

上述代码中,使用 @NoArgsConstructor 注解为 User 类自动创建了一个无参构造方法,可以通过该构造方法创建 User 实例,并使用 setter 方法设置对象的属性。例如:

User user = new User();
user.setId(1L);
user.setName("Tom");
user.setAge(20);

3.4 @RequiredArgsConstructor

@RequiredArgsConstructor 是 Lombok 提供的注解之一,可以自动为类的 final 属性生成一个构造方法,这个构造方法会接收所有 final 属性作为参数,用于方便地创建对象。

举例

@RequiredArgsConstructor
public class User {
    private final Long id;
    private final String name;
    private Integer age;
}

在上面的示例中,@RequiredArgsConstructor 注解自动为 User 类生成了一个构造方法,该方法包含了该类中所有的 final 属性,即 id 和 name。这样,我们就可以直接使用该构造方法创建 User 实例,而不需要手动为这些属性设置值,例如:

User user = new User(1L, "Tom");

3.5 @Getter 和 @Setter

Lombok 提供了 @Getter@Setter 注解,可以在编写 Java 类的时候自动生成对应属性的 Getter 和 Setter 方法。通过使用这两个注解,可以省去手写 Getter 和 Setter 方法的时间和精力,同时也减少了代码量,提高了代码的可读性。

举例

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Person {
    
    private String name;
    private int age;
    
}

在这个例子中,我们使用了 @Getter@Setter 注解来对 nameage 属性生成对应的 Getter 和 Setter 方法。这样我们就可以在其他类中对这些属性进行读写操作了。使用方式非常简单,只需要在类的头部添加这两个注解即可。

需要注意的是,@Getter@Setter 注解可以应用于类级别、字段级别和方法级别。在字段级别时,注解会生成对应字段的 Getter 和 Setter 方法;在类级别时,注解会为类中所有字段生成 Getter 和 Setter 方法;在方法级别时,注解只为该方法生成 Getter 和 Setter 方法,这些方法的名称就是该方法名(去掉 get 或 set 前缀之后的部分)。

如果想通过注解来限制 Getter 和 Setter 的访问性,@Getter@Setter 注解都提供了 AccessLevel 参数来实现。例如,要将 age 属性的 Setter 方法的访问性设置为 protected,可以这样写:

@Getter
@Setter(access = AccessLevel.PROTECTED)
public class Person {
    
    private String name;
    private int age;
    
}

这样,age 的 Setter 方法的访问性就被限制为 protected 了。

3.6 @ToString

Lombok 提供了 @ToString 注解,可以自动为类生成 toString() 方法,方便打印对象的属性信息。通过使用 @ToString 注解,可以省去手动编写 toString() 方法的时间和精力,同时也提高了代码的可读性。

举例

import lombok.ToString;

@ToString
public class Person {

    private String name;
    private int age;

    // 构造方法、Getter 和 Setter 方法
}

在这个例子中,我们使用了 @ToString 注解来自动生成 toString() 方法,其中包括 nameage 属性的信息。通过调用 toString() 方法,可以将该对象的属性信息打印出来。

需要注意的是,@ToString 注解还支持一些参数,用于自定义生成的字符串的格式。例如,可以使用 includeFieldNames 参数来包含字段名称,使用 exclude 参数来排除某些字段,使用 of 参数来指定要包含的字段等。

import lombok.ToString;

@ToString(includeFieldNames=true, exclude={"password"})
public class User {
    
    private String username;
    private String password;
    private int age;
    
}

在这个例子中,我们指定了 includeFieldNames 参数为 true,表示在输出字符串中包含字段名称;使用了 exclude 参数来排除 password 字段,即不在输出字符串中包含该字段的信息。

总之,使用 @ToString 注解可以非常方便地生成 toString() 方法,以便于打印对象的属性信息。

3.7 @Builder

@Builder 是 Lombok 提供的一个注解,它能够自动生成一个包含多个参数的构造方法,使得创建对象的代码更加简洁、易读。

使用 @Builder 注解时,需要满足以下条件:

  1. 必须使用 private 访问修饰符修饰所有希望在构建器中设置的属性;
  2. 类必须为最终类或具有无参构造函数;
  3. 必须是非静态内部类或顶级类。

举例

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Person {
    private String name;
    private int age;
    private String address;
}


在这个示例中,我们使用 @Builder 注解为 Person 类生成了一个构造器,我们可以使用以下代码来创建 Person 对象:

Person person = Person.builder()
                .name("Tom")
                .address("Beijing")
                .age(20)
                .build();

在构造器中,使用了流畅的 API 链式调用的方式,通过调用 builder() 方法返回了一个 PersonBuilder 对象,并在后续的方法调用中依次设置了 nameaddressage 这三个属性。最后通过调用 build() 方法创建对象。

需要注意的是,@Builder 注解生成的构造器方法返回的是一个建造者对象,不是实际的目标类型对象。使用建造者对象可以很方便地为目标类型对象的属性赋值。如果需要返回实际的目标类型对象,需要调用 build() 方法。

3.8 @Slf4j

@Slf4j 是 Lombok 提供的注解之一,它可以自动生成一个名为 logorg.slf4j.Logger 类型的常量,可以方便地用于日志输出。使用该注解的类可以直接使用 log 常量输出日志信息。

使用 @Slf4j 注解时,只需在类上加上该注解即可

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Test {
    public static void main(String[] args) {
        log.info("Hello, world!");
    }
}

在上述示例中,我们使用了 @Slf4j 注解来添加日志支持,并在 main 方法中使用 log 常量输出了一条日志信息。

需要注意的是,在使用 @Slf4j 注解之前,需要提前引入 slf4j-api 和任意一个 slf4j 实现(例如 logback-classic)。如果没有引入这些库,会有编译错误。

3.9 @EqualsAndHashCode

@EqualsAndHashCode 是 Lombok 提供的注解之一,它可以自动生成 equalshashCode 方法的实现。

使用 @EqualsAndHashCode 注解时,可以指定需要使用哪些字段参与 equalshashCode 方法的判断。默认情况下,@EqualsAndHashCode 注解会使用所有非静态和非瞬态的字段(即没有被 transient 关键字修饰)来生成 equalshashCode 方法。

举例

import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class Person {
    private String name;
    private int age;
}


使用 @EqualsAndHashCode 注解之后,生成的代码等价于下面手写的代码:

public class Person {
    private String name;
    private int age;

    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof Person)) return false;
        Person other = (Person) o;
        return this.name.equals(other.name) &&
                this.age == other.age;
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + this.name.hashCode();
        result = 31 * result + this.age;
        return result;
    }
}

需要注意的是,@EqualsAndHashCode 注解默认使用所有非静态和非瞬态的字段来生成 equalshashCode 方法,如果某些字段不需要参与判断,则可以使用 excludeof 属性来排除或显式指定需要参与判断的字段。

例如,我们可以使用 exclude 属性来排除 age 字段,示例代码如下:

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(exclude = "age")
public class Person {
    private String name;
    private int age;
}

上述代码会生成一个只使用 name 字段生成 equalshashCode 方法的 Person 类。

同时,我们还可以使用 of 属性来显式指定需要参与判断的字段,示例代码如下:

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(of = {"name", "age"})
public class Person {
    private String name;
    private int age;
}

上述代码会生成一个只使用 nameage 字段生成 equalshashCode 方法的 Person 类。

注意:它默认仅使用该类中定义的属性且不调用父类的方法,可通过callSuper=true解决这一问题。让其生成的方法中调用父类的方法。

问题

当使用@Data注解时,则有了@EqualsAndHashCode注解,那么就会在此类中存在equals(Object other) 和 hashCode()方法,且不会使用父类的属性,这就导致了可能的问题。

比如,有多个类有相同的部分属性,把它们定义到父类中,恰好id(数据库主键)也在父类中,那么就会存在部分对象在比较时,它们并不相等,却因为lombok自动生成的equals(Object other) 和 hashCode()方法判定为相等,从而导致出错。

解决方案

  1. 使用@Getter @Setter @ToString代替@Data并且自定义equals(Object other) 和 hashCode()方法,比如有些类只需要判断主键id是否相等即足矣。

  2. 或者使用在使用@Data时同时加上@EqualsAndHashCode(callSuper=true)注解。

文章来源:https://blog.csdn.net/qq_62357662/article/details/132782859
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。