使用lombok从现有对象构建对象


105

可以说我有一个龙目岛注释类

@Builder
class Band {
   String name;
   String type;
}

我知道我可以做:

Band rollingStones = Band.builder().name("Rolling Stones").type("Rock Band").build();

是否有一种简单的方法可以使用现有对象作为模板并更改其属性之一来创建Foo对象?

就像是:

Band nirvana = Band.builder(rollingStones).name("Nirvana");

我在lombok文档中找不到此文件。

Answers:


232

您可以使用toBuilder参数为实例提供toBuilder()方法。

@Builder(toBuilder=true)
class Foo {
   int x;
   ...
}

Foo f0 = Foo.builder().build();
Foo f1 = f0.toBuilder().x(42).build();

文档中

如果使用@Builder生成生成器来生成您自己的类的实例(除非将@Builder添加到不返回您自己的类型的方法中,否则总是这样),您可以使用@Builder(toBuilder = true)来生成类中的一个实例方法,称为toBuilder(); 它创建一个新的构建器,该构建器以该实例的所有值开始。

免责声明:我是lombok开发人员。


12
@Mustafa还有一个@Wither,对于单字段更改更有效:Foo f1 = f0.withX(42)
maaartinus

我认为@maaartinus会@Wither生成with *方法,该方法始终返回一个新对象,而不是设置现有对象的字段。这是低效率的。
MGhostSoft '19

3
@MGhostSoft我显然以创建新对象为目标。因此,随着不可变对象的使用越来越多,我们非常常见。++×对于更改单个字段,@Wither最好。胜过两个,toBuilder获胜。请参阅下面的答案。
maaartinus

2
对于零字段(即没有任何更改的对象副本),@Wither它将完全不起作用.toBuilder().build()
M. Justin

40

是否有一种简单的方法可以使用现有对象作为模板并更改其属性之一来创建Foo对象?(重点是我的

如果您真的想更改单个属性,那么有一种更好,更有效的方法:

@With
class Band {
   String name;
   String type;
}

Band nirvana = rollingStones.withName("Nirvana");

凋灵不会产生垃圾,但只能更改一个字段。要更改许多字段,您可以使用

withA(a).withB(b).withC(c)....

并产生大量垃圾(所有中间结果),但toBuilder效率更高,更自然。

注意:较早版本的lombok已使用@Wither注释。请参阅文档开头


1
真的会产生那么多垃圾吗?我认为这是所有浅表副本,除了您要替换的字段(依赖于这样的想法:如果这是您想要的,您将使对象已经不可变)。“垃圾”将主要是丢弃的顶级对象的引用(尽管我猜很多原语也可能导致更多垃圾)。
jm0

1
@ jm0当然,都是浅表副本。“大量垃圾”是指n-1一系列对的n调用的对象withSomething。一个对象的成本大约是几个字节加上每个引用4或8个字节加上每个原语1到8个字节。因此,我们正在谈论每个调用数十个字节。通常没什么大不了的。
maaartinus 19'Apr
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.