Bojan Vukasovic
Bojan Vukasovic

Reputation: 2268

Lombok Nullable value

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

Answers (1)

Eugene
Eugene

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

Related Questions