Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用lombok从现有对象构建对象_Java_Lombok - Fatal编程技术网

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

Java 使用lombok从现有对象构建对象,java,lombok,Java,Lombok,假设我有一个lombok注释类,比如 @Builder class Band { String name; String type; } 我知道我能做到: Band rollingStones = Band.builder().name("Rolling Stones").type("Rock Band").build(); 有没有一种简单的方法可以使用现有对象作为模板创建Foo对象并更改其属性之一 比如: Band nirvana = Band.builder(rollingS

假设我有一个lombok注释类,比如

@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文档中找不到这一点。

您可以使用
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开发者

有没有一种简单的方法可以使用现有对象作为模板创建Foo对象,并更改其一个属性? (强调矿山)

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

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

Band nirvana = rollingStones.withName("Nirvana");
wither不会创建垃圾,但它只能更改单个字段。要更改许多字段,可以使用

withA(a).withB(b).withC(c)....
并产生成吨的垃圾(都是中间结果),但比
toBuilder
更高效、更自然


注:lombok的旧版本使用了
@Wither
注释。请参阅。

您可能还需要使用
com.fasterxml.jackson.databind.ObjectMapper创建对象的副本

@AllArgsConstructor
@Setter
class Band {
    String name;
    String type;
}

ObjectMapper objectMapper = new ObjectMapper(); //it's configurable
objectMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
objectMapper.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );

Band rollingStones = new Band("Rolling Stones", "Rock Band");

Band nirvana = objectMapper.convertValue( rollingStones, Band.class);
nirvana.setName("Nirvana");

它可以很容易地包装在一些实用方法中,以便在整个项目中使用,例如
ConvertUtils.clone(rollingStones,Band.class)

@Mustafa还有
@Wither
,它对于单字段更改更有效:
Foo f1=f0.withX(42)
@maaartinus我认为
@Wither
使用*方法生成,该方法总是返回一个新对象,而不是设置现有对象的字段。这效率很低。@MGhostSoft我显然认为创建一个新对象是他们的目标。因此,随着不可变对象的使用越来越多,我们变得非常普遍++×对于更改单个字段,
@Wither
是最佳选择。超过两个时,
toBuilder
获胜。请参阅下面我的答案。对于零字段(即没有任何更改的对象副本),
@Wither
根本不起作用,但
.toBuilder().build()
将是完美的答案!它真的会产生那么多垃圾吗?我认为除了要替换的字段之外,所有的都是浅拷贝(这取决于这样一个概念,即如果你想要的话,你将使对象不可变)。“垃圾”主要是被丢弃的顶级对象的引用(尽管我猜很多原语也会导致更多的垃圾)。@jm0当然,它们都是浅拷贝。我所说的“垃圾吨”是指一系列
n
调用
n-1
对象。一个对象的成本大约为几个字节加上每个引用4或8字节加上每个原语1到8字节。所以我们说的是每次调用几十个字节。通常没什么大不了的。