62

I am using Lombok's @Data and @Builder annotations like this:

@Data
@Builder(toBuilder = true)
class Movie {

    // Some other fields here.

    private final List<Actor> actors;

}

When I create a new Movie using the builder, without specifying any actors, I would expect Lombok to initialize my List to Collections.emptyList(). But this does not happen:

List<Actor> actors = Movie.builder().build().getActors();
System.out.println(actors); // Prints 'null'.

In the documentation for the @Builder annotation, it is stated at line 55 and 56 in the code-example for Vanilla Java (https://projectlombok.org/features/Builder.html) that I should look at the code example for @Singular (https://projectlombok.org/features/Singular-snippet.html). At line 112 in the Vanilla Java example here, it seems like the list should be initialized to the empty list.

I checked, and it does indeed happen if I annotate the list with @Singular:

@Data
@Builder(toBuilder = true)
class Movie {

    // Some other fields here.

    @Singular
    private final List<Actor> actors;

}

List<Actor> actors = Movie.builder().build().getActors();
System.out.println(actors); // Prints '[]'.

Is this a bug in Lombok, or is there something that I am doing wrong? According to the documentation, it seems like the list should be initialized to the empty list in both cases (because the @Builder doc refers to the @Singular doc).

marstran
  • 26,413
  • 5
  • 61
  • 67

2 Answers2

100

Only when you use @Singular, you get an empty list. On the Builder documentation page it says:

…with the @Singular annotation, lombok will treat that builder node as a collection.

Without the @Singular, lombok treats it as any other object. So it will be null instead of an empty Collection.

Disclosure: I am a Lombok developer

Roel Spilker
  • 32,258
  • 10
  • 68
  • 58
  • 1
    Thanks! By the way, the `@Singular` annotation gives an error if the variable name of the collection can't be singularized. However, this is a little inconvenient when you have an uncountable noun as a variable name (such as the word "equipment", or "sheep"). Why can't the generated singular method be named the same as the plural one, instead of giving a compile error? – marstran Sep 30 '15 at 06:49
  • 1
    Our short research let us to believe there are not many of those words used in actual software. Whenever lombok is unsure, we err on the safe side. Isn't it a warning? – Roel Spilker Oct 01 '15 at 11:18
  • 3
    I realized I can just specify the name like this `@Singular("equipment")`, and it worked. Thanks for your help! – marstran Oct 01 '15 at 11:37
  • 5
    Or you can use `@Builder.Default` annotation and initialise that filed yourself. – Ondřej Stašek Mar 20 '19 at 09:34
  • I tried to use @Singular but my list is still null and not an empty list... – Wrong Aug 27 '19 at 07:14
  • Awesome feature. In fact I think it should become the default. – Jeroen Kransen Dec 12 '20 at 06:25
32

Since Lombok v1.16.16, you can use @Builder‘s inner annotation to initialize your collection by default. For example:

@Data
@Builder
class Movie {

@Builder.Default
private final List<Actor> actors = new ArrayList<>();

}

So when you create a new Movie using the builder, without specifying any actors:

Movie movie = Movie.builder().build();
movie.getActors(); // Will return instance of ArrayList
Kovsharov
  • 396
  • 4
  • 12
  • This worked for me (w Lombok v. 1.18.12). For me this was the better answer as this solves exactly the problem (same as OP) without needing the `@Singular` annotation, which changes other `@Builder` behaviour I did not want. – Wardibald Apr 22 '21 at 08:23
  • Without the `final` modifier, this removes the default for the constructor call and might result in NPE. – Valerij Dobler Sep 19 '22 at 07:20