Java 在集合字段上使用复数方法时会产生不同的效果,有@Singular注释和没有@Singular注释

Java 在集合字段上使用复数方法时会产生不同的效果,有@Singular注释和没有@Singular注释,java,lombok,Java,Lombok,我想要不可变的myClass对象。使用@Singular注释是一个很好的解决方案。 问题是,当我使用此注释时,方法elements()会将元素附加到现有列表中,而不是创建新列表: 假设我们有: @Value @Builder(toBuilder = true) public class MyClass { @Singular private List<String> elemets; } 如果没有@Singular注释,列表中就有elem2 对于@Singular

我想要不可变的myClass对象。使用@Singular注释是一个很好的解决方案。 问题是,当我使用此注释时,方法elements()会将元素附加到现有列表中,而不是创建新列表:

假设我们有:

@Value
@Builder(toBuilder = true)
public class MyClass  {
    @Singular
    private List<String> elemets;
}
如果没有@Singular注释,列表中就有elem2 对于@Singular annotation,我们有elem1和elem2,如果我只想有elem2,我必须先使用clearElements()

为什么实现不同?是否可以在我自己的实现中使用@Singular


使用@Singular annotation,我无法在MyClassBuilder类中实现elemets(List elemets)方法,因为我得到:“不支持手动添加@Singular@Builder将生成的方法。如果要手动管理此字段/参数的生成器特性,请不要使用@Singular。”

首先让我说,使用
@Singular
不一定是最好的解决方案——这取决于您的用例。 但是,在大多数情况下,如果希望确保使用集合的类的不变性,那么这是一个不错的选择

@Singular
的行为方式与之相同,因为Lombok设计师认为这是一个很好的选择。我同意:它使两个setter方法的行为相似;在极少数情况下,您需要重置生成器中的元素,您可以使用
clear
方法

@Singular
生成相当复杂的代码(参见示例)。这是为了确保像效率和不变性这样的属性(在重用构建器生成多个对象时也是如此)。当你乱搞这些代码时,你很容易违反这些属性。Lombok阻止你这么做

如果确实要修改此特性,则有三种选择:

  • delombok
    builder代码,将其复制到类中,然后对其进行修改
  • 添加另一个不同名称的方法,如
    clearAndSetElements(List)
    。但这可能更令人困惑
  • 删除
    @Singular
    并自己实现setter方法。如果您想要获得Lombok实现的属性,您必须在实现中付出一些努力;您可以使用
    delombok
    ed代码作为灵感

谢谢您的回答。1.在第一种选择中,我将不得不放弃龙目山的优势。2.因为我的任务是使类对象不可变,并且类已经在使用中(有些字段带有单数注释),所以我决定不添加任何额外的方法。作为静态MyClassBuilder类的一部分,我去掉了单数注释并实现了自己的elemets()和element()方法。在这些方法中,我每次都创建一个新的不可变列表。我还自己实现了getter方法,因此它返回空的ImmutableList而不是NULL(以防止NPE)。我在我的答案中加上了你的答案。
MyClass.builder()
.elemets(Arrays.asList("elem1"))
.elemets(Arrays.asList("elem2"))
.build();