繁体   English   中英

使用 lombok,required-arg 构造函数可以与 @Value、@Builder 和 @Builder.Default 注释共存吗?

[英]With lombok, can required-arg constructor coexist with @Value, @Builder and @Builder.Default annotations?

使用 lombok (1.18.24),是否可以生成(1)一个只接受非初始化成员的参数的构造函数以及(2)一个构建器? 我尝试了多种注释集:

  1. []
@Value @Builder class Foo {
    String alpha;
    @Builder.Default String bravo = "x";
    Foo(String alpha) {this.alpha = alpha;}
    static void bar() {new Foo("y");}
}
[ERROR] Foo.java:[6,8] constructor Foo in class Foo cannot be applied to given types;
[ERROR]   required: java.lang.String
[ERROR]   found:    java.lang.String,java.lang.String
[ERROR]   reason: actual and formal argument lists differ in length
  1. [AllArgsConstructor]
@Value @Builder @AllArgsConstructor class Foo {
    String alpha;
    @Builder.Default String bravo = "x";
    Foo(String alpha) {this.alpha = alpha;}
    static void bar() {new Foo("y");}
}
[ERROR] Foo.java:[11,47] variable bravo might not have been initialized
  1. [RequiredArgsConstructor]
@Value @Builder @RequiredArgsConstructor class Foo {
    String alpha;
    @Builder.Default String bravo = "x";
    static void bar() {new Foo("y");}
}
[ERROR] Foo.java:[10,29] constructor Foo in class Foo cannot be applied to given types;
[ERROR]   required: java.lang.String,java.lang.String
[ERROR]   found:    java.lang.String
[ERROR]   reason: actual and formal argument lists differ in length
  1. [AllArgsConstructor, RequiredArgsConstructor]
@Value @Builder @AllArgsConstructor @RequiredArgsConstructor class Foo {
    String alpha;
    @Builder.Default String bravo = "x";
    static void bar() {new Foo("y");}
}
[ERROR] constructor Foo(java.lang.String,java.lang.String) is already defined in class Foo
[ERROR] Foo.java:[8,37] constructor Foo(java.lang.String,java.lang.String) is already defined in class Foo
  1. Lombok 为您制作了一个全参数构造函数,除非您自己编写一个构造函数,在这种情况下,您必须添加@AllArgsConstructor 你应该在这里做什么。 如果你愿意,你可以将它设为私有( @AllArgsConstructor(access = AccessLevel.PRIVATE)的构建器需要存在它才能创建对象。它需要包含默认的东西(这只是默认设置,因此构建器需要也能够传递非默认值)。

  2. 问题出在您自己的代码中 - 您编写了自己的构造函数,它没有设置bravo字段。 一般来说,拥有自己的构造函数是一个坏主意,特别是如果所述构造函数调用 lombok 生成的构造函数。 @Builder.Default修改构建器的功能(即:如果您要求构建器build()而没有为其设置bravo的值,它将使用该"X"值)。 它删除了那个"X" ,当然@Value已经使那个字段成为final字段 - 所以,你的构造函数无法设置一个未初始化的(因为构建器“带走了"X"final字段,这是一个编译器错误.

  3. 同样的问题。

  4. AllArgs 和 RequiredArgs 是相同的构造函数,因此 lombok 尝试同时生成它们,但这是行不通的。

@Value @Builder @AllArgsConstructor class Foo {
    String alpha;
    @Builder.Default String bravo = "x";
    Foo(String alpha) {this(alpha, "x");}
    static void bar() {new Foo("y");}
}

是你要找的。 或者,更有可能的是,摆脱那个构造函数,然后写:

@Value @Builder @AllArgsConstructor class Foo {
    String alpha;
    @Builder.Default String bravo = "x";
    static void bar() {return builder().alpha("y").build(); }
}

在编程中混合任何东西通常不是一个好主意——而你在这里混合了你的构建方法。 某些自定义构造函数,某些自定义构造函数,另一些自定义构造函数。 如果必须的话,好吧,但是,这是有代价的。 代价之一是混乱(这似乎已经发生在这里)。 另一种是容易出错的代码:不易发现的错误(因为一个人总是使用一种方式,因此另一种方式的错误不在他们的任何代码路径中,但在你的代码路径中)。 第三是风格辩论; 如果有两种方法可以做同样的事情,任何一种代码都会任意选择一种方法(这很糟糕;通过以不同的方式做同样的事情,导致代码不必要地难以阅读,这错误地暗示读者要么担心,或者会花一些时间去追查,不,事实上,这并不重要——或者,你需要一个风格指南来决定何时使用哪种方式。然后你需要强制执行这种风格指南很难做到;大多数人通常不想花时间编写自定义 lint 规则)。

注意:我说的是“通常不是一个好主意”——而不是“它总是错的”。 杂交有充分的理由,但要注意引入它是有代价的。 因此,提出论点的责任在于混合方法的作者。 他们需要解释,尽管用多种方法来做同一件事会带来巨大的成本,但在这里仍然是值得的。 您的代码显然是一个简化的示例,目的是为了提出一个简化的 SO 问题(非常好),所以这里也许一个很好的理由。 但是,在可能没有的情况下 - 摆脱那个手写的构造函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM