Reputation: 6134
Lets say I have a Lombok annotated class like
@Builder
class Band {
String name;
String type;
}
I know I can do:
Band rollingStones = Band.builder()
.name("Rolling Stones")
.type("Rock Band")
.build();
Is there an easy way to create an object of Band
using the existing object as a template and changing one of its properties?
Something like:
Band nirvana = Band.builder(rollingStones)
.name("Nirvana");
I can't find this in the Lombok documentation.
Upvotes: 252
Views: 189846
Reputation: 964
You might also want do a copy of the object using 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");
it can be easily wrapped in some utility method to be used all over the project like ConvertUtils.clone(rollingStones, Band.class)
Upvotes: 2
Reputation: 46492
Is there an easy way to create an object of Foo using the existing object as a template and changing one of it's properties? (emphasis mine)
If you really want to change a single property, then there's a nicer and more efficient way:
@With
class Band {
String name;
String type;
}
Band nirvana = rollingStones.withName("Nirvana");
The wither creates no garbage, but it can change just a single field. For changing many fields, you could use
withA(a).withB(b).withC(c)....
and produce tons of garbage (all intermediate results) but than toBuilder
is more efficient and more natural.
NOTE: Older versions of lombok have used @Wither
annotation. See beginning of documentation.
Upvotes: 83
Reputation: 34562
You can use the toBuilder
parameter to give your instances a toBuilder()
method.
@Builder(toBuilder=true)
class Foo {
int x;
...
}
Foo f0 = Foo.builder().build();
Foo f1 = f0.toBuilder().x(42).build();
From the documentation:
If using @Builder to generate builders to produce instances of your own class (this is always the case unless adding @Builder to a method that doesn't return your own type), you can use @Builder(toBuilder = true) to also generate an instance method in your class called toBuilder(); it creates a new builder that starts out with all the values of this instance.
Disclaimer: I am a lombok developer.
Upvotes: 537