使用 Lombok Builder 注释抛出 UnsupportedOperationException

UnsupportedOperationException is thrown with Lombok Builder annotation

我正在为我的项目使用 Lombok。 我的模型看起来像:

@Builder
@Data @AllArgsConstructor
public class ScreenDefinitionDTO {
    @Singular
    private List<ScreenDeclaration> screens;
}

我要进行下一步操作:

String screenName = ctx.screenName().getText();
ScreenDeclaration declaration = ParsingUtils
                .buildScreenDeclaration(StringUtils.trim(screenName));

创建实例的位置:

public static ScreenDefinitionDTO buildEmptyScreenDTO() {
    return ScreenDefinitionDTO.builder()
            .screens(new ArrayList<>())
            .build();
}

最后,我得到了:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at java.util.AbstractList.add(AbstractList.java:108)

当我更改创建没有 Lombok 构建器模式的实例时,一切都很好:

public static ScreenDefinitionDTO buildEmptyScreenDTO() {
    return new ScreenDefinitionDTO(new ArrayList<>());
}

我无法理解 Lombok 的构建器模式有什么问题?

由于 GitHub issue

Lombok @Builder is primarily meant for immutables (and uses either Collections.unmodifiableList or Guava's ImmutableList

这就是为什么你 UnsupportedOperationException

为了更加确定地重现您有异常的完整代码模式。

如@fbokovikov 所述,@Builder 注释使用不可变,因此当您尝试在列表中添加元素时会抛出异常。

dto.getScreens().add(new ScreenDeclaration()) // throws java.lang.UnsupportedOperationException

如果你设置一个断点来查看dto.getScreens()返回的值,你可以看到它的类型是Collections$EmptyList。如果使用 DTO 的构造函数,则类型为 ArrayList 并且不会抛出异常。

试试这个:

@Builder
@Data @AllArgsConstructor
public class ScreenDefinitionDTO {
    @Builder.Default
    private List<ScreenDeclaration> screens = new ArrayList<>();
}

这样你就告诉 lombok 在构建时用空的 ArrayList.

初始化 screens