Lombok的@Builder无法初始化集合

62

我正在使用Lombok的@Data@Builder注解,如下所示:

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

    // Some other fields here.

    private final List<Actor> actors;

}

当我使用构建器创建一个新的电影对象时,如果没有指定任何演员,我希望Lombok会将我的List初始化为Collections.emptyList()。但是这并没有发生:
List<Actor> actors = Movie.builder().build().getActors();
System.out.println(actors); // Prints 'null'.

@Builder注释的文档中,Vanilla Java代码示例(https://projectlombok.org/features/Builder.html)的第55和56行指出我应该查看@Singular的代码示例(https://projectlombok.org/features/Singular-snippet.html)。在此处的Vanilla Java示例的第112行中,似乎应该将列表初始化为空列表。
我检查了一下,如果我使用@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 '[]'.

这是Lombok的一个Bug吗?还是说我做错了什么?根据文档,两种情况下该列表都应该被初始化为空列表(因为@Builder文档引用了@Singular文档)。

顺便说一下,我正在使用的是 Lombok 版本 1.16.6。 - marstran
2个回答

100
只有使用@Singular时,你才会得到一个空列表。在构建器文档页面上,它说:

…使用@Singular注释,lombok会将该构建器节点视为集合。

没有@Singular,lombok将其视为任何其他对象。因此,它将是null而不是空集合。
披露:我是Lombok开发人员

1
谢谢!顺便说一下,如果集合的变量名无法转换为单数形式,则@Singular注释会出现错误。然而,当您将不可数名词作为变量名(例如“equipment”或“sheep”)时,这有点不方便。为什么不能将生成的单数方法命名为复数方法相同,而不是产生编译错误呢? - marstran
1
我们的短期研究让我们相信,在实际软件中使用这些词语的不多。每当lombok不确定时,我们会选择保守一些。这不是一个警告吗? - Roel Spilker
3
我意识到我可以这样指定名称: @Singular("equipment"),它起作用了。感谢你的帮助! - marstran
5
你可以使用@Builder.Default注解并自行初始化该字段。 - Ondřej Stašek
我尝试使用@Singular,但我的列表仍然为空而不是空列表... - Wrong
显示剩余2条评论

32

自 Lombok v1.16.16 版本起,您可以使用 @Builder 的内部注释来默认初始化集合。例如:

@Data
@Builder
class Movie {

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

}

因此,当您使用生成器创建新电影时,没有指定任何演员:

Movie movie = Movie.builder().build();
movie.getActors(); // Will return instance of ArrayList

这对我有用(使用 Lombok v. 1.18.12)。对我来说,这是更好的答案,因为它解决了与 OP 相同的问题,而不需要 @Singular 注释,该注释会改变其他我不想要的 @Builder 行为。 - Wardibald
没有 final 修饰符,这会移除构造函数调用的默认值,可能导致 NPE。 - Valerij Dobler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接