J'ai un objet
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
Et je l'initialise de deux manières
UserInfo ui = new UserInfo();
UserInfo ui2 = UserInfo.builder().build();
System.out.println("ui: " + ui.isEmailConfirmed());
System.out.println("ui2: " + ui2.isEmailConfirmed());
Voici la sortie
ui: true
ui2: false
Il semble que le constructeur n'obtienne pas de valeur par défaut. J'ajoute l'annotation @Builder.Default
à ma propriété et mon objet ressemble maintenant à ceci
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
@Builder.Default
private boolean isEmailConfirmed = true;
}
Voici la sortie de la console
ui: false
ui2: true
Comment puis-je faire les deux être true
?
J'imagine que ce n'est pas possible (sans avoir supprimé le code). Mais pourquoi ne pas simplement implémenter le constructeur dont vous avez besoin? Lombok est conçu pour vous faciliter la vie, et si quelque chose ne fonctionne pas avec Lombok, il suffit de le faire à l’ancienne.
@Data
@Builder
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
@Builder.Default
private boolean isEmailConfirmed = true;
public UserInfo(){
isEmailConfirmed = true;
}
}
Sortie de la console:
ui: true
ui2: true
Comme @Builder.Default
l'annotation est cassée , je ne l'emploierais pas du tout. Vous pouvez toutefois utiliser l'approche suivante:
@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);
}
}
De cette façon, vous vous assurez:
isEmailConfirmed
n'est initialisé qu'à un seul endroit, ce qui rend le code moins sujet aux erreurs et plus facile à gérer ultérieurementUserInfo
sera initialisée de la même manière que vous utilisiez un générateur ou un constructeur sans argumentEn d'autres termes, la condition contient true
:
new UserInfo().equals(UserInfo.builder().build())
Dans ce cas, la création d'objet est cohérente quelle que soit la manière dont vous le créez. Cela est particulièrement important lorsque votre classe est utilisée par une infrastructure de mappage ou par un fournisseur JPA lorsque vous ne l'instanciez pas manuellement par un générateur mais qu'un constructeur no-args est appelé dans votre dos pour créer l'instance.
L'approche décrite ci-dessus est très similaire mais présente un inconvénient majeur. Vous devez initialiser le champ à deux endroits, ce qui rend le code sujet aux erreurs car vous devez garder les valeurs cohérentes.
Vous pouvez également définir votre propre méthode getterannulation la lombok 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;
}
}
Voici mon approche:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
Puis
UserInfo ui = new UserInfo().toBuilder().build();
Les constructeurs personnalisés et @Builder.Default
ne fonctionneront probablement jamais ensemble.
Les auteurs de framework veulent éviter les doubles initialisations pour @Builder
.
Je réutilise .builder()
par public static CLAZZ of(...)
méthodes:
@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();
}
}
Vérifiez la discussion correspondante: https://github.com/rzwitserloot/lombok/issues/1347