在 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 之外的每个变量似乎都可能在未来发生变化。