Java lombok 中的默认值。如何使用构造函数和构建器初始化默认值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47883931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Default value in lombok. How to init default with both constructor and builder
提问by Vitalii
I have an object
我有一个对象
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
And I initialize it in two ways
我用两种方式初始化它
UserInfo ui = new UserInfo();
UserInfo ui2 = UserInfo.builder().build();
System.out.println("ui: " + ui.isEmailConfirmed());
System.out.println("ui2: " + ui2.isEmailConfirmed());
Here is output
这是输出
ui: true
ui2: false
It seems that builder does not get a default value. I add @Builder.Default
annotation to my property and my object now looks like this
似乎 builder 没有获得默认值。我@Builder.Default
向我的属性添加注释,我的对象现在看起来像这样
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
@Builder.Default
private boolean isEmailConfirmed = true;
}
Here is console output
这是控制台输出
ui: false
ui2: true
How can I make them both be true
?
我怎样才能让他们都成为true
?
采纳答案by Michael A. Schaffrath
My guess is that it's not possible (without having delomboked the code). But why don't you just implement the constructor you need? Lombok is meant to make your life easier, and if something won't work with Lombok, just do it the old fashioned way.
我的猜测是这是不可能的(没有对代码进行 delomboked)。但是你为什么不实现你需要的构造函数呢?Lombok 旨在让您的生活更轻松,如果 Lombok 无法解决某些问题,请按照老式方法进行操作。
@Data
@Builder
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
@Builder.Default
private boolean isEmailConfirmed = true;
public UserInfo(){
isEmailConfirmed = true;
}
}
Console output:
控制台输出:
ui: true
ui2: true
回答by Sahil Chhabra
Another way is define your own gettermethod overridingthe lombokgetter:
另一种方法是定义你自己的getter方法覆盖的龙目岛的getter:
@Data
@Builder
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
private Boolean isEmailConfirmed;
public Boolean getIsEmailConfirmed(){
return Objects.isNull(isEmailConfirmed) ? true : isEmailConfirmed;
}
}
回答by Marcin K?opotek
Since the @Builder.Default
annotation is broken, I wouldn't use it at all. You can, however, use the following approach by moving the @Builder
annotation from class level to the custom constructor:
由于@Builder.Default
注释已损坏,我根本不会使用它。但是,您可以通过将@Builder
注释从类级别移动到自定义构造函数来使用以下方法:
@Data
@NoArgsConstructor
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
@Builder
@SuppressWarnings("unused")
private UserInfo(int id, String nick, Boolean isEmailConfirmed) {
this.id = id;
this.nick = nick;
this.isEmailConfirmed = Optional.ofNullable(isEmailConfirmed).orElse(this.isEmailConfirmed);
}
}
This way you ensure:
这样您可以确保:
- the field
isEmailConfirmed
is initialized only in one place making the code less error-prone and easier to maintain later - the
UserInfo
class will be initialized the same way either you use a builder or a no-args constructor
- 该字段
isEmailConfirmed
仅在一处初始化,从而使代码不易出错且以后更易于维护 - 该
UserInfo
班将被初始化或者您使用的助洗剂或无参数的构造以同样的方式
In other words, the condition holds true
:
换句话说,条件成立true
:
new UserInfo().equals(UserInfo.builder().build())
In that case, the object creation is consistent no matter how you create it. It is especially important when your class is used by a mapping framework or by JPA provider when you are not instantiating it manually by a builder but a no-args constructor is invoked behind your back to create the instance.
在这种情况下,无论您如何创建对象,对象创建都是一致的。当您的类被映射框架或 JPA 提供者使用时,当您不是由构建器手动实例化它,而是在背后调用无参数构造函数来创建实例时,这一点尤其重要。
The approach described aboveis very similar but it has a major drawback. You have to initialize the field in two places which makes the code error-prone as you are required to keep the values consistent.
该方法上面描述的非常相似,但它有一个很大的缺点。您必须在两个地方初始化该字段,这会使代码容易出错,因为您需要保持值一致。
回答by laurent
Here's my approach :
这是我的方法:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
And then
进而
UserInfo ui = new UserInfo().toBuilder().build();
回答by gavenkoa
Custom constructors and @Builder.Default
probably will never work together.
自定义构造函数@Builder.Default
可能永远不会一起工作。
Framework authors want to avoid double initializations for @Builder
.
框架作者希望避免对@Builder
.
I reuse .builder()
by public static CLAZZ of(...)
methods:
我.builder()
通过public static CLAZZ of(...)
方法重用:
@Builder
public class Connection {
private String user;
private String pass;
@Builder.Default
private long timeout = 10_000;
@Builder.Default
private String port = "8080";
public static Connection of(String user, String pass) {
return Connection.builder()
.user(user)
.pass(pass)
.build();
}
public static Connection of(String user, String pass, String port) {
return Connection.builder()
.user(user)
.pass(pass)
.port(port)
.build();
}
public static Connection of(String user, String pass, String port, long timeout) {
return Connection.builder()
.user(user)
.pass(pass)
.port(port)
.timeout(timeout)
.build();
}
}
Check corresponding discussion: https://github.com/rzwitserloot/lombok/issues/1347
回答by LordOfThePigs
My experience is that @Builder
works best when it is the only means of instantiating a class, and therefore works best when paired with @Value
rather than @Data
.
我的经验是@Builder
效果最好时,它是一个类实例化的唯一途径,因此,当与配对的效果最好@Value
,而不是@Data
。
For classes where all fields are mutable in any order anyway, and for which you want to keep the chained calls, consider replacing it with @Accessors(chain=true)
or @Accessors(fluent=true)
.
对于所有字段都以任何顺序可变的类,并且您希望保留链接调用,请考虑将其替换为@Accessors(chain=true)
或@Accessors(fluent=true)
。
@Data
@Accessors(fluent=true)
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
This allows you to construct your objects fluently in the code, and avoid un-necessary creation of Builder objects:
这使您可以在代码中流畅地构建对象,并避免不必要地创建 Builder 对象:
UserInfo ui = new UserInfo().id(25).nick("John");
回答by ifelse.codes
Initialize the properties in the No-Arg Constructor
初始化 No-Arg 中的属性 Constructor
convertedprivate boolean isEmailConfirmed = true;
转换private boolean isEmailConfirmed = true;
to
到
public class UserInfo {
public UserInfo() {
this.isEmailConfirmed = true;
}
}
回答by Andrey Serebryanskiy
In version 1.18.2 both @NoArgsConstructor
and @Builder
work, but not completely.
在 1.18.2 版本中@NoArgsConstructor
和 都可以@Builder
工作,但不完全。
Constructor with one or more fields will null all other default initialisations: new UserInfo("Some nick")
will cause isEmailConfirmed
to be false again.
具有一个或多个字段的构造函数将使所有其他默认初始化为空:new UserInfo("Some nick")
将isEmailConfirmed
再次导致为假。
My way to handle this is:
我的处理方法是:
public UserInfo(String nick) {
this();
this.nick = nick;
}
This way all default fields will be initialised and we'll get expected constructor.
这样所有默认字段都将被初始化,我们将获得预期的构造函数。
回答by George L
You can create a static Builder class with default values populated:
您可以创建一个静态 Builder 类,并填充默认值:
@Data
@Builder(builderClassName="Builder")
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed;
public static class Builder{
//Set defaults here
private boolean isEmailConfirmed = true;
}
}