Reputation: 2268
I have the following code using Lombok:
class Query1 {
@Builder
static class Something{
Inner inner;
public Optional<Inner> getInner() {
return Optional.ofNullable(inner);
}
}
@Value
static class Inner{
Integer value;
}
public static void main (String[] args) {
Integer mayBeNull = 123;
Something s = Something.builder()
.inner(mayBeNull == null ? null : new Inner(mayBeNull)) //THIS LINE IS UGLY
.build();
System.out.println(s.getInner().map(Inner::getValue).orElse(987));
}
}
Is it possible to somehow shorten this line mayBeNull == null ? null : new Inner(mayBeNull)
using some Lombok magic, or is there some other idiom that I could use here? Basically if Inner
value is null, there is no reason for me to set inner
field inside Something
at all.
The only thing that comes up to my mind is manually adding:
@Value
static class Inner{
Integer value;
public static Inner ofNullable(Integer value){
return value!=null ? new Inner(value) : null;
}
}
and then using it as a .inner(Inner.ofNullable(mayBeNull))
but this one also doesn't feel right to me.
Upvotes: 1
Views: 3881
Reputation: 6005
You can move this null
check and Inner
object creation into the builder. We can customize a Lombok builder. We write the parts of the builder that we want to customize and the Lombok @Builder
annotation will simply not generate those parts, but just extend builder with missed fields.
Example 1, additional method for Inner
field initialization:
@Builder
public class Something {
Inner inner;
ClassA classA;
public Optional<Inner> getInner() {
return Optional.ofNullable(inner);
}
public static class SomethingBuilder {
private Inner inner;;
public SomethingBuilder innerInt(Integer mayBeNull) {
this.inner = mayBeNull == null ? null : new Inner(mayBeNull); // or Inner.ofNullable(mayBeNull)
return this;
}
}
}
Generated code:
public static class SomethingBuilder {
private Inner inner;;
private ClassA classA;
SomethingBuilder() {
}
public SomethingBuilder innerInt(Integer mayBeNull) {
this.inner = mayBeNull == null ? null : new Inner(mayBeNull);
return this;
}
public SomethingBuilder inner(Inner inner) {
this.inner = inner;
return this;
}
public SomethingBuilder classA(ClassA classA) {
this.classA = classA;
return this;
}
public Something build() {
return new Something(inner, classA);
}
public String toString() {
return "Something.SomethingBuilder(inner=" + this.inner + ", classA=" + this.classA + ")";
}
}
}
Example 2, replace method for Inner
field initialization:
@Builder
public class Something {
Inner inner;
ClassA classA;
public Optional<Inner> getInner() {
return Optional.ofNullable(inner);
}
public static class SomethingBuilder {
private Inner inner;;
public SomethingBuilder inner(Integer mayBeNull) {
this.inner = mayBeNull == null ? null : new Inner(mayBeNull);// or Inner.ofNullable(mayBeNull)
return this;
}
}
}
Generated code:
public static class SomethingBuilder {
private Inner inner;;
private ClassA classA;
SomethingBuilder() {
}
public SomethingBuilder inner(Integer mayBeNull) {
this.inner = mayBeNull == null ? null : new Inner(mayBeNull);
return this;
}
public SomethingBuilder classA(ClassA classA) {
this.classA = classA;
return this;
}
public Something build() {
return new Something(inner, classA);
}
public String toString() {
return "Something.SomethingBuilder(inner=" + this.inner + ", classA=" + this.classA + ")";
}
}
Usage:
Something something1 = Something.builder().innerInt(null).build();
Something something2 = Something.builder().innerInt(123).build();
Something something3 = Something.builder().inner(new Inner(123)).build();
Upvotes: 1