Lombok 提供的 @Value
注解可以帮助我们轻松实现不可变类(immutable class)。不可变类的特点是它的状态在对象创建后不能被修改,这在多线程环境中尤其有用。@Value
注解是 @Data
的不可变版本,自动生成所有字段的 getter 方法、toString
方法、equals
和 hashCode
方法,以及一个全参数的构造函数,并将所有字段设为 private
和 final
。
@Value
的基本使用
自动生成不可变类
示例:
import lombok.Value;
@Value
public class Person {
private String name;
private int age;
private String address;
}
在这个例子中,Lombok 会自动生成 Person
类的以下内容:
- 所有字段的
private
和final
修饰符。 - 包含所有字段的全参数构造函数。
- 所有字段的 getter 方法。
toString
方法。equals
和hashCode
方法。
等价于:
public final class Person {
private final String name;
private final int age;
private final String address;
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getAddress() {
return address;
}
@Override
public String toString() {
return "Person(name=" + this.name + ", age=" + this.age + ", address=" + this.address + ")";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name) && Objects.equals(address, person.address);
}
@Override
public int hashCode() {
return Objects.hash(name, age, address);
}
}
@Value
的详细特性
- 不可变字段:所有字段都被设为
private
和final
。 - 全参数构造函数:生成一个包含所有字段的构造函数。
- getter 方法:生成所有字段的 getter 方法。
toString
方法:生成包含所有字段的toString
方法。equals
和hashCode
方法:生成基于所有字段的equals
和hashCode
方法。
自定义 @Value
注解
虽然 @Value
注解生成的类默认是不可变的,但我们仍然可以通过一些 Lombok 提供的选项进行定制。
自定义示例
示例:
import lombok.Value;
import lombok.With;
import lombok.NonNull;
@Value
public class User {
@NonNull private String username;
@With private String email;
private String password;
}
在这个例子中:
username
字段被标记为@NonNull
,因此生成的构造函数会进行非空检查。email
字段被标记为@With
,生成一个返回新对象的方法,以便我们可以创建新的实例并保留不可变性。password
字段不会生成with
方法,因为它没有被@With
注解。
等价于:
import java.util.Objects;
public final class User {
private final String username;
private final String email;
private final String password;
public User(String username, String email, String password) {
if (username == null) {
throw new NullPointerException("username is marked non-null but is null");
}
this.username = username;
this.email = email;
this.password = password;
}
public String getUsername() {
return username;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
public User withEmail(String email) {
return new User(this.username, email, this.password);
}
@Override
public String toString() {
return "User(username=" + this.username + ", email=" + this.email + ", password=" + this.password + ")";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(username, user.username) && Objects.equals(email, user.email) && Objects.equals(password, user.password);
}
@Override
public int hashCode() {
return Objects.hash(username, email, password);
}
}
安装和配置 Lombok
-
添加 Lombok 依赖:在你的项目中添加 Lombok 依赖(例如使用 Maven 或 Gradle)。
Maven:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> <scope>provided</scope> </dependency>
Gradle:
dependencies { compileOnly 'org.projectlombok:lombok:1.18.20' annotationProcessor 'org.projectlombok:lombok:1.18.20' }
-
在 IDE 中启用 Lombok 支持:
- IntelliJ IDEA:安装 Lombok 插件,并在设置中启用注解处理。
- Eclipse:安装 Lombok 插件,并在设置中启用注解处理。
结合实际案例
假设我们有一个简单的产品类,需要不可变性和各种常见的方法。
示例:
import lombok.Value;
@Value
public class Product {
private String name;
private double price;
private String category;
}
在这个例子中,Lombok 会自动生成 Product
类的以下内容:
- 所有字段的
private
和final
修饰符。 - 包含所有字段的全参数构造函数。
- 所有字段的 getter 方法。
toString
方法。equals
和hashCode
方法。
通过使用 Lombok 的 @Value
注解,我们可以大大简化 Java 类中的样板代码,使代码更加简洁和易于维护,同时保证对象的不可变性。