在Java 15记录中,将值设置为其中一个属性

28

我在我的代码中使用了Java 15预览功能record,并将该record定义如下

public record ProductViewModel
        (
                String id,
                String name,
                String description,
                float price
        ) {
}

在控制器层我有以下代码

@Put(uri = "/{id}")
public Maybe<HttpResponse> Update(ProductViewModel model, String id) {
        LOG.info(String.format("Controller --> Updating the specified product"));
        return iProductManager.Update(id, model).flatMap(item -> {
            if(item == null)
                return Maybe.just(HttpResponse.notFound());
            else
                return Maybe.just(HttpResponse.accepted());
        });
    }

从模型的用户界面中未传递 id 的值,但是它作为路由参数传递。现在我想在控制器级别设置该值,类似于:

从模型的用户界面中未传递id的值,但是它作为路由参数传递。现在我想在控制器层面设置该值,就像这样:

model.setid(id) // Old style

我该如何设置记录特定属性的值?

3个回答

45

你无法更改记录的属性,因为它们是不可变的。然而,你可以添加一个 wither 方法来创建一个带有相同属性但新 id 的新记录:

public record ProductViewModel(String id,
                               String name, 
                               String description,
                               float price) {

    public ProductViewModel withId(String id) {
        return new ProductViewModel(id, name(), description(), price());
    }
} 

7
拥有类似于Scala中case class的copy方法将是非常好的。 - Mandroid
2
还没有达到目标,但是…… https://github.com/openjdk/amber-docs/blob/master/eg-drafts/reconstruction-records-and-classes.md - daniel
你还可以使用Lombok的@With注解 - https://www.baeldung.com/lombok-with-annotations - undefined

8
如果您需要更改一个属性,那么您需要使用一个 class 而不是一个 record
从该JEP中可以看到:
增强Java编程语言的记录功能,这些类作为不可变数据的透明载体。 记录可以被视为名义元组。
因此,如果您需要这种行为,则最好使用类。

1
我还要补充一点,你明确将你的类命名为“model”,这通常意味着它是可变的。 - stridecolossus
2
@stridecolossus 不,通常情况下不会。实际上,在领域驱动设计中,大部分的领域模型都将是值对象,根据定义它们没有行为,因此应该是不可变的(这是由于对于值而言,除了值本身之外没有身份概念)。 - Amadán

6
你无法修改它们。来自Oracle页面的内容如下:

记录类是一种浅不可变的、透明的承载固定值集合(称为记录成分)的对象。 Java语言提供了简洁的语法来声明记录类,其中记录成分在记录头中声明。在记录头中声明的记录成分列表形成记录描述符。

从Java语言规范第8.10节可以读到如下内容:

记录声明隐式地是final的。允许记录类的声明冗余地指定final

还有

8.10.3 记录成员

对于出现在记录成分列表中的每个记录成分,记录类都具有一个隐式声明的字段,该字段与记录成分具有相同的名称和声明类型。 该字段被声明为private和final。 该字段带有注释,如果在相应的记录成分上出现注释类型,则该注释类型适用于字段声明上下文或类型上下文或两者兼而有之。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接