官网
? 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 的优点包括:
Lombok 的缺点是它对编译器的支持不够友好,有时候可能会导致编译器的报错、警告和 IDE 的智能提示问题。
总之,Lombok 是一款非常流行的 Java 工具类库,可以极大地提高 Java 开发效率和代码质量。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
? @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);
@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);
@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);
@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");
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
注解来对 name
和 age
属性生成对应的 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
了。
Lombok 提供了 @ToString
注解,可以自动为类生成 toString()
方法,方便打印对象的属性信息。通过使用 @ToString
注解,可以省去手动编写 toString()
方法的时间和精力,同时也提高了代码的可读性。
举例
import lombok.ToString;
@ToString
public class Person {
private String name;
private int age;
// 构造方法、Getter 和 Setter 方法
}
在这个例子中,我们使用了 @ToString
注解来自动生成 toString()
方法,其中包括 name
和 age
属性的信息。通过调用 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()
方法,以便于打印对象的属性信息。
@Builder
是 Lombok 提供的一个注解,它能够自动生成一个包含多个参数的构造方法,使得创建对象的代码更加简洁、易读。
使用 @Builder
注解时,需要满足以下条件:
private
访问修饰符修饰所有希望在构建器中设置的属性;举例
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
对象,并在后续的方法调用中依次设置了 name
、address
和 age
这三个属性。最后通过调用 build()
方法创建对象。
需要注意的是,@Builder
注解生成的构造器方法返回的是一个建造者对象,不是实际的目标类型对象。使用建造者对象可以很方便地为目标类型对象的属性赋值。如果需要返回实际的目标类型对象,需要调用 build()
方法。
@Slf4j
是 Lombok 提供的注解之一,它可以自动生成一个名为 log
的 org.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
)。如果没有引入这些库,会有编译错误。
@EqualsAndHashCode
是 Lombok 提供的注解之一,它可以自动生成 equals
和 hashCode
方法的实现。
使用 @EqualsAndHashCode
注解时,可以指定需要使用哪些字段参与 equals
和 hashCode
方法的判断。默认情况下,@EqualsAndHashCode
注解会使用所有非静态和非瞬态的字段(即没有被 transient
关键字修饰)来生成 equals
和 hashCode
方法。
举例
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
注解默认使用所有非静态和非瞬态的字段来生成 equals
和 hashCode
方法,如果某些字段不需要参与判断,则可以使用 exclude
或 of
属性来排除或显式指定需要参与判断的字段。
例如,我们可以使用 exclude
属性来排除 age
字段,示例代码如下:
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(exclude = "age")
public class Person {
private String name;
private int age;
}
上述代码会生成一个只使用 name
字段生成 equals
和 hashCode
方法的 Person
类。
同时,我们还可以使用 of
属性来显式指定需要参与判断的字段,示例代码如下:
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(of = {"name", "age"})
public class Person {
private String name;
private int age;
}
上述代码会生成一个只使用 name
和 age
字段生成 equals
和 hashCode
方法的 Person
类。
注意:它默认仅使用该类中定义的属性且不调用父类的方法,可通过callSuper=true解决这一问题。让其生成的方法中调用父类的方法。
问题
当使用@Data注解时,则有了@EqualsAndHashCode注解,那么就会在此类中存在equals(Object other) 和 hashCode()方法,且不会使用父类的属性,这就导致了可能的问题。
比如,有多个类有相同的部分属性,把它们定义到父类中,恰好id(数据库主键)也在父类中,那么就会存在部分对象在比较时,它们并不相等,却因为lombok自动生成的equals(Object other) 和 hashCode()方法判定为相等,从而导致出错。
解决方案
使用@Getter @Setter @ToString代替@Data并且自定义equals(Object other) 和 hashCode()方法,比如有些类只需要判断主键id是否相等即足矣。
或者使用在使用@Data时同时加上@EqualsAndHashCode(callSuper=true)注解。