在 Java 中使用 Lombok 更新不可变对象?
Update an immutable object with Lombok in Java?
我有一个域 class Person
用 Lombok 注释 @Value
因此将其标记为不可变的,具有 3 个字段。
在我的服务层,我正在调用存储库以检查此人是否存在。
如果它确实存在,我需要从数据库中取出 Person
对象并更新 money
字段。
因为它是不可变的,所以不能这样做。我正在阅读一些文章,发现这可以使用构建器模式来完成。
我可能需要在我的 Person
class 中创建一个 updatePerson()
,但不确定如何操作。或者我需要做其他事情吗?
Person.java
:
@Value
@Builder
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
}
我正在使用 Java15.
使用Lombok
:
@Value
@Builder(toBuilder = true)
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
}
personObjectFromDatabase.toBuilder().setMoney(...).build()
或
在这种情况下,您可以使用 Builder
模式:
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
public static class PersonBuilder {
private UUID id;
private String job;
private BigDecimal money;
public PersonBuilder(Person defaultPerson){
this.id = defaultPerson.getId();
this.job = defaultPerson.getJob();
this.money = defaultPerson.getMoney();
}
public PersonBuilder withId(UUID id) {
this.id = UUID;
return this;
}
public PersonBuilder withJob(String job) {
this.job = job;
return this;
}
public PersonBuilder withMoney(BigDecimal money) {
this.money = money;
return this;
}
public Person build() {
return new Person(id, job, money);
}
}
}
像下面这样使用这个构建器:
Person person = new Person.PersonBuilder(personObjectFromDatabase)
.withMoney(...)
.build();
或
您可以只创建一个 copyWith()
方法:
public class Person {
...
public Person copyWith(BigDecimal money) {
return new Person(this.id, this.job, money);
}
}
class是不可变的;
您永远无法更改 class.
实例的值
相反,
您必须创建 class.
的新实例
不写构建器;
你已经在使用龙目岛,
只需使用
@Builder
注释和 Lombok 将为您创建一个构建器。
编辑:您正在使用构建器注释。
您正在寻找的解决方案似乎是这样的:
您必须创建 class 的新实例。
您还可以使用 lombok 的另一个功能,它不需要您使用构建器。它被称为 @With
并且使用这个注释将创建不可变的 setters,这意味着 setter returns 一个新对象具有旧对象的属性,除了你想改变。
@Value
public class Person {
/* You don't need to write final if you are using @Value. Lombok will make the variables final for you.
In theory you do not even need to write private,
because Lombok makes variables private by default instead of package private.*/
private UUID id;
private String job;
@With
private BigDecimal money;
}
Person newPerson = person.withMoney(new Big decimal("10"));
总的来说,我不确定使对象不可变是否真的是个好主意。除了 UUID 之外的每个变量似乎都可能在未来发生变化。
我有一个域 class Person
用 Lombok 注释 @Value
因此将其标记为不可变的,具有 3 个字段。
在我的服务层,我正在调用存储库以检查此人是否存在。
如果它确实存在,我需要从数据库中取出 Person
对象并更新 money
字段。
因为它是不可变的,所以不能这样做。我正在阅读一些文章,发现这可以使用构建器模式来完成。
我可能需要在我的 Person
class 中创建一个 updatePerson()
,但不确定如何操作。或者我需要做其他事情吗?
Person.java
:
@Value
@Builder
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
}
我正在使用 Java15.
使用Lombok
:
@Value
@Builder(toBuilder = true)
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
}
personObjectFromDatabase.toBuilder().setMoney(...).build()
或
在这种情况下,您可以使用 Builder
模式:
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
public static class PersonBuilder {
private UUID id;
private String job;
private BigDecimal money;
public PersonBuilder(Person defaultPerson){
this.id = defaultPerson.getId();
this.job = defaultPerson.getJob();
this.money = defaultPerson.getMoney();
}
public PersonBuilder withId(UUID id) {
this.id = UUID;
return this;
}
public PersonBuilder withJob(String job) {
this.job = job;
return this;
}
public PersonBuilder withMoney(BigDecimal money) {
this.money = money;
return this;
}
public Person build() {
return new Person(id, job, money);
}
}
}
像下面这样使用这个构建器:
Person person = new Person.PersonBuilder(personObjectFromDatabase)
.withMoney(...)
.build();
或
您可以只创建一个 copyWith()
方法:
public class Person {
...
public Person copyWith(BigDecimal money) {
return new Person(this.id, this.job, money);
}
}
class是不可变的; 您永远无法更改 class.
实例的值相反, 您必须创建 class.
的新实例不写构建器;
你已经在使用龙目岛,
只需使用
@Builder
注释和 Lombok 将为您创建一个构建器。
编辑:您正在使用构建器注释。 您正在寻找的解决方案似乎是这样的:
您必须创建 class 的新实例。
您还可以使用 lombok 的另一个功能,它不需要您使用构建器。它被称为 @With
并且使用这个注释将创建不可变的 setters,这意味着 setter returns 一个新对象具有旧对象的属性,除了你想改变。
@Value
public class Person {
/* You don't need to write final if you are using @Value. Lombok will make the variables final for you.
In theory you do not even need to write private,
because Lombok makes variables private by default instead of package private.*/
private UUID id;
private String job;
@With
private BigDecimal money;
}
Person newPerson = person.withMoney(new Big decimal("10"));
总的来说,我不确定使对象不可变是否真的是个好主意。除了 UUID 之外的每个变量似乎都可能在未来发生变化。