Vérifiez deux arguments en Java, tous deux non nuls ou tous les deux nuls avec élégance

161

J'ai utilisé Spring Boot pour développer un projet shell utilisé pour envoyer des e-mails, par exemple

sendmail -from foo@bar.com -password  foobar -subject "hello world"  -to aaa@bbb.com

Si les arguments fromet passwordmanquent, j'utilise un expéditeur et un mot de passe par défaut, par exemple [email protected]et 123456.

Donc, si l'utilisateur transmet l' fromargument, il doit également passer l' passwordargument et vice versa. Autrement dit, soit les deux sont non nuls, soit les deux sont nuls.

Comment puis-je vérifier cela avec élégance?

Maintenant ma voie est

if ((from != null && password == null) || (from == null && password != null)) {
    throw new RuntimeException("from and password either both exist or both not exist");
}
zhuguowei
la source
14
En passant, notez comment l'utilisation des espaces blancs rend le code beaucoup plus facile à lire - le simple fait d'ajouter des espaces entre les opérateurs dans votre code actuel ajouterait considérablement à la lisibilité IMO.
Jon Skeet le
8
Veuillez définir «élégance».
Renaud le
Vous avez besoin d'un ensemble d'arguments distinct pour les informations d'authentification SMTP et pour l'adresse e-mail de l'expéditeur de l'enveloppe. L' Fromadresse e-mail n'est pas toujours le nom d'authentification SMTP.
Kaz le
3
Il ne peut vraiment pas être beaucoup plus optimisé, c'est une ligne de code lisible et rien ne peut être gagné en le suroptimisant.
diynevala
3
Note latérale: s'il s'agit d'un script shell, les mots de passe ne seront-ils pas enregistrés dans l'historique du shell?
touche mon corps

Réponses:

331

Il existe un moyen d'utiliser l' opérateur ^( XOR ):

if (from == null ^ password == null) {
    // Use RuntimeException if you need to
    throw new IllegalArgumentException("message");
}

La ifcondition sera vraie si une seule variable est nulle.

Mais je pense qu'en général, il est préférable d'utiliser deux ifconditions avec des messages d'exception différents. Vous ne pouvez pas définir ce qui a mal tourné en utilisant une seule condition.

if ((from == null) && (password != null)) {
    throw new IllegalArgumentException("If from is null, password must be null");
}
if ((from != null) && (password == null)) {
    throw new IllegalArgumentException("If from is not null, password must not be null");
}

Il est plus lisible et beaucoup plus facile à comprendre, et il suffit d'un peu de frappe supplémentaire.

Un gars sympa
la source
152
Y a-t-il une raison pour laquelle xor sur deux bools est préférable à !=deux bools?
Eric Lippert le
1
Wow, je ne savais pas que XOR sur booléen est le même que !=. L'esprit soufflé. Et c'est un nombre très élevé de votes positifs dans le commentaire. Et, pour ajouter de la qualité à ce commentaire, oui, je pense également qu'il est préférable de donner un message d'erreur différent pour différents cas d'erreur, car l'utilisateur saura mieux comment corriger l'erreur.
justhalf
1
Pour 2 éléments, c'est bien. Comment faire cela avec> 2 éléments?
Anushree Acharjee
Je veux afficher un message d'erreur si l'un des éléments est> 0. Par défaut, tous sont mis à 0. Si tous sont> 0, c'est un scénario valide. Comment faire cela?
Anushree Acharjee
Cela ferait une question d'entretien astucieuse. Je me demande ce que% des programmeurs savent. Mais je ne suis pas d'accord pour dire que ce n'est pas assez clair et qu'il justifie de se diviser en 2 ifclauses - le message dans l'exception le documente bien (j'ai édité la question, mais elle n'apparaîtra pas avant d'être acceptée)
Adam
286

Eh bien, il semble que vous essayez de vérifier si la condition de «nullité» des deux est la même ou non. Vous pouvez utiliser:

if ((from == null) != (password == null))
{
    ...
}

Ou rendez-le plus explicite avec des variables d'assistance:

boolean gotFrom = from != null;
boolean gotPassword = password != null;
if (gotFrom != gotPassword)
{
    ...
}
Jon Skeet
la source
18
Vous êtes l'un de mes SO heros @Kaz, mais rien ne dit `` ni ceci ni cela, mais pas les deux pareils '' comme le ^fait. :-)
David Bullock
6
@DavidBullock: En ce qui concerne les booléens, rien ne dit "ni ceci ni cela mais pas les deux identiques" comme ... "pas les deux identiques"; XOR est juste un autre nom pour la fonction "not equals" sur les booléens.
Kaz
5
@Kaz C'est juste que ça ^dit "Hé, mes opérandes sont des booléens" d'une manière qui !=ne le fait pas. (Bien que cet effet soit malheureusement diminué par la nécessité de vérifier "mes opérandes pourraient être numériques, et je ne serais peut-être pas un opérateur relationnel à ce stade", ce que j'accorde est un inconvénient). Votre statut de héros intact, malgré votre désaccord avec moi :-)
David Bullock
3
Après avoir lu les exigences du problème, puis votre solution, le code a du sens et est lisible. Mais en tant que développeur de 4 ans (toujours à l'école), lire ce code puis essayer de comprendre quelle «exigence commerciale» était en place serait un casse-tête. A partir de ce code, je ne comprends pas tout de suite " fromet passworddoivent être tous les deux nuls ou tous deux non nuls". C'est peut-être juste moi et mon inexpérience, mais je préfère la solution la plus lisible comme dans la réponse de @ stig-hemmer, même si cela coûte encore 3 lignes de code. Je suppose que je ne comprends tout simplement pas immédiatement bool != bool- ce n'est pas intuitif.
Chris Cirefice
2
@DavidBullock L' ^opérateur est un opérateur au niveau du bit; cela n'implique en fait pas que ses opérandes sont booléens. L'opérateur booléen xor est xor.
Brilliand
222

Personnellement, je préfère le lisible à l'élégant.

if (from != null && password == null) {
    throw new RuntimeException("-from given without -password");
}
if (from == null && password != null) {
    throw new RuntimeException("-password given without -from");
}
Stig Hemmer
la source
52
+1 pour les meilleurs messages. Ceci est important, personne n'aime les messages d'erreur "quelque chose s'est mal passé" , donc personne ne devrait provoquer de tels messages. Cependant, dans la pratique, on devrait préférer une exception plus spécifique (en particulier, une IllegalArgumentExceptionau lieu d'un nu RuntimeException)
Marco13
6
@matt il semble que votre critique ne concerne pas le code, mais le texte des exceptions. Mais je pense que le mérite de cette réponse réside dans la structure des instructions if, pas dans le contenu des messages d'erreur. C'est la meilleure réponse car elle améliore la fonctionnalité; OP pourrait facilement remplacer les chaînes de caractères souhaitées par les textes d'exception.
Dan Henderson
4
@matt L'avantage est qu'il devient possible de distinguer lequel des deux états invalides s'est produit et de personnaliser le message d'erreur. Ainsi, au lieu de dire "vous avez mal fait l'une de ces deux choses", vous pouvez dire "vous avez fait ceci" ou "vous avez fait cela" (et ensuite, passez à des étapes de résolution, si vous le souhaitez). La résolution peut être la même dans les deux cas, mais ce n'est jamais une bonne idée de dire "vous avez mal fait l'une de ces choses". Source: dans un environnement dans lequel je n'étais pas en mesure de fournir cette fonctionnalité, j'ai répondu à de nombreuses questions d'utilisateurs ayant satisfait à la première condition de mon texte d'erreur.
Dan Henderson
4
@DanHenderson> ce n'est jamais une bonne idée de dire "vous avez mal fait une de ces choses". Je ne suis pas d'accord. Mot de passe / nom d'utilisateur, il est plus sûr de dire simplement que le nom d'utilisateur et le mot de passe ne correspondent pas.
mat du
2
@DanHenderson Du point de vue de la sécurité, il peut être préférable de ne pas faire de distinction entre le cas où le nom d'utilisateur est dans le répertoire ou non, sinon un attaquant pourrait trouver des noms d'utilisateur valides. Cependant, mélanger NULL / NON NULL est (dans ce cas) toujours une erreur d'utilisation et afficher un message d'erreur plus détaillé ne divulgue pas plus d'informations que l'utilisateur fourni en premier lieu.
siegi
16

Mettez cette fonctionnalité dans une méthode à 2 arguments avec la signature:

void assertBothNullOrBothNotNull(Object a, Object b) throws RuntimeException

Cela économise de l'espace dans la méthode qui vous intéresse et la rend plus lisible. Il n'y a rien de mal avec les noms de méthode légèrement verbeux et il n'y a rien de mal avec les méthodes très courtes.

Traubenfuchs
la source
14
Aucun espace économisé, ((from == null) != (password == null))c'est très simple à comprendre aussi. Il y a quelque chose qui ne va pas avec les méthodes inutiles.
edc65
3
Il y a une ligne pour l'instruction if, la deuxième ligne pour l'instruction throw et la troisième ligne pour l'accolade fermante: toutes remplacées par une ligne. Une ligne de plus enregistrée si vous donnez une nouvelle ligne aux accolades fermantes!
Traubenfuchs
10
Lors de la lecture du code, vous avez un nom de méthode dont vous avez besoin pour comprendre la jonglerie vs condition.
Traubenfuchs
1
définitivement +1, préférez toujours faire abstraction des détails et des opérateurs d'implémentation down-and-dirty avec des méthodes descriptives et des noms de variables qui rendent INTENTION clair. la logique contient des bogues. les commentaires sont encore pires. un nom de méthode montre l'intention et isole la logique afin qu'il soit plus facile de trouver et de corriger les erreurs. cette solution n'exige pas que le lecteur connaisse ou réfléchisse à la syntaxe ou à la logique du tout, elle nous permet de nous concentrer sur les EXIGENCES COMMERCIALES à la place (ce qui compte vraiment)
sara
1
Vous rencontreriez des problèmes inutiles si vous vouliez avoir un message d'exception descriptif ici.
Honza Brabec
11

Une solution Java 8 serait à utiliser Objects.isNull(Object), en supposant une importation statique:

if (isNull(from) != isNull(password)) {
    throw ...;
}

Pour Java <8 (ou si vous n'aimez pas utiliser Objects.isNull()), vous pouvez facilement écrire votre propre isNull()méthode.

Didier L
la source
6
Je n'aime pas ça. from == null != password == nullgarde tout sur le même cadre de la pile, mais en utilisant Objects.isNull(Object)inutilement pousse et fait éclater deux cadres. Objects.isNull (Object) est là parce que 'Cette méthode existe pour être utilisée comme prédicat' (c'est-à-dire dans les flux).
David Bullock
5
Une méthode simple comme celle-ci sera normalement rapidement intégrée par le JIT, de sorte que l'impact sur les performances est probablement négligeable. Nous pourrions en effet débattre de l'utilisation de Objects.isNull()- vous pouvez écrire le vôtre si vous préférez - mais en ce qui concerne la lisibilité, je pense qu'il isNull()est préférable d' utiliser . De plus vous avez besoin entre parenthèses supplémentaires pour rendre le simple , la compilation d'expression: from == null != (password == null).
Didier L
2
Je suis d'accord sur le JIT'ing (et l'ordre des opérations ... j'étais paresseux). Pourtant, (val == null)est tellement la facilité fournie dans le but de comparer avec null, j'ai du mal à surmonter deux grosses invocations de méthode qui me regardent en face, même si la méthode est assez fonctionnelle, intégrable et bien- nommé. Mais c'est juste moi. J'ai décidé récemment que je suis un peu bizarre.
David Bullock
4
honnêtement, qui se soucie d'un cadre à pile unique? la pile n'est toujours un problème que si vous avez affaire à une récursivité (éventuellement infinie), ou si vous avez une application à 1000 niveaux avec un graphique d'objets de la taille du désert du Sahara.
sara
9

Voici une solution générale pour n'importe quel nombre de vérifications nulles

public static int nulls(Object... objs)
{
    int n = 0;
    for(Object obj : objs) if(obj == null) n++;
    return n;
}

public static void main (String[] args) throws java.lang.Exception
{
    String a = null;
    String b = "";
    String c = "Test";

    System.out.println (" "+nulls(a,b,c));
}

Les usages

// equivalent to (a==null & !(b==null|c==null) | .. | c==null & !(a==null|b==null))
if (nulls(a,b,c) == 1) { .. }

// equivalent to (a==null | b==null | c==null)
if (nulls(a,b,c) >= 1) { .. }

// equivalent to (a!=null | b!=null | c!=null)
if (nulls(a,b,c) < 3) { .. }

// equivalent to (a==null & b==null & c==null)
if (nulls(a,b,c) == 3) { .. }

// equivalent to (a!=null & b!=null & c!=null)
if (nulls(a,b,c) == 0) { .. }
Khaled.K
la source
2
Bonne approche, mais votre premier commentaire "équivalent à" est horriblement faux (au-delà de la faute d'orthographe qui existe dans tous les commentaires)
Ben Voigt
@BenVoigt Merci pour l'avis, corrigé maintenant
Khaled.K
9

Puisque vous voulez faire quelque chose de spécial (utilisez les valeurs par défaut) lorsque l'expéditeur et le mot de passe sont absents, gérez-le d'abord.
Après cela, vous devriez avoir à la fois un expéditeur et un mot de passe pour envoyer un e-mail; lancer une exception si l'un ou l'autre est manquant.

// use defaults if neither is provided
if ((from == null) && (password == null)) {
    from = DEFAULT_SENDER;
    password = DEFAULT_PASSWORD;
}

// we should have a sender and a password now
if (from == null) {
    throw new MissingSenderException();
}
if (password == null) {
    throw new MissingPasswordException();
}

Un avantage supplémentaire est que, si l'une de vos valeurs par défaut est nulle, cela sera également détecté.


Cela dit, en général, je pense que l'utilisation de XOR devrait être autorisée lorsque c'est l'opérateur dont vous avez besoin. Il est une partie de la langue, pas seulement un truc qui fonctionne à cause d'un compilateur bug Arcane.
Une fois, j'ai eu un cow-orker qui a trouvé l'opérateur ternaire trop déroutant à utiliser ...

SQB
la source
1
Évalué parce que j'ai fait un choix aléatoire pour échantillonner l'une de vos réponses et que je ne trouve pas le lien xkcd promis! Honte à toi!
dhein
@Zaibis Pour ma défense, c'est juste un passe-temps, pas un travail à plein temps. Mais je vais voir si je peux en trouver un ...
SQB
8

Je voudrais suggérer une autre alternative, comment j'écrirais réellement ce morceau de code:

if( from != null )
{
    if( password == null )
        error( "password required for " + from );
}
else
{
    if( password != null )
        warn( "the given password will not be used" );
}

Cela me semble être la manière la plus naturelle d'exprimer cette condition qui la rend facile à comprendre pour quelqu'un qui pourrait avoir à la lire à l'avenir. Cela vous permet également de donner des messages de diagnostic plus utiles et de traiter le mot de passe inutile comme moins sérieux et il est facile de modifier ce qui est plutôt probable pour une telle condition. Par exemple, vous découvrirez peut-être que donner un mot de passe comme argument de ligne de commande n'est pas la meilleure idée et que vous voudrez peut-être autoriser la lecture du mot de passe à partir de l'entrée standard si l'argument est manquant. Ou vous pouvez ignorer silencieusement l'argument de mot de passe superflu. Des changements comme ceux-ci ne vous obligeraient pas à tout réécrire.

De plus, il n'exécute que le nombre minimum de comparaisons, donc ce n'est pas plus cher que les alternatives plus "élégantes" . Bien que les performances soient très peu probables, un problème ici, car le démarrage d'un nouveau processus est déjà beaucoup plus coûteux qu'une vérification de null supplémentaire.

x4u
la source
Je commente quelque peu conversationnellement, donc je pourrais suivre cela autrement avec un "// nous avons un nul de". La brièveté de l'exemple rend cela vraiment mineur. J'aime la clarté de la logique et la réduction des tests que cela présente.
The Nate
Cela fonctionne parfaitement bien, mais imbriquer les déclarations me semble moins clair et plus encombré. Ce n'est qu'une opinion personnelle, donc je suis heureux que cette réponse soit ici comme une autre option
Kevin Wells
En ce qui concerne l'élégance, c'est probablement l'une des façons les moins élégantes de le faire.
dramzy
7

Je pense qu'une manière correcte de gérer cela est de considérer trois situations: à la fois «de» et «mot de passe» sont fournis, aucun n'est fourni, un mélange des deux est fourni.

if(from != null && password != null){
    //use the provided values
} else if(from == null && password == null){
    //both values are null use the default values
} else{
   //throw an exception because the input is not correct.
}

Il semble que la question d'origine veuille interrompre le flux s'il s'agit d'une entrée incorrecte, mais ils devront ensuite répéter une partie de la logique plus tard. Peut-être qu'une bonne déclaration de lancer pourrait être:

throw new IllegalArgumentException("form of " + form + 
    " cannot be used with a "
    + (password==null?"null":"not null") +  
    " password. Either provide a value for both, or no value for both"
);
mat
la source
2
Ce code est faux non pas parce qu'il ne fonctionne pas, mais parce qu'il est très difficile à comprendre. Déboguer ce genre de code, écrit par quelqu'un d'autre, n'est qu'un cauchemar.
NO_NAME
2
@NO_NAME Je ne vois pas pourquoi c'est difficile à comprendre. L'OP a fourni trois cas: lorsque le formulaire et le mot de passe sont fournis, lorsque ni l'un ni l'autre n'est fourni, et le cas mixte qui devrait lever une exception. Faites-vous référence au conditionnel du milieu pour vérifier s'ils sont tous les deux nuls?
mat du
2
Je suis d'accord avec @NO_NAME, cette casse du milieu demande trop d'analyse pour être examinée. Sauf si vous analysez la ligne du haut, vous n'obtenez pas que null n'a rien à voir avec le milieu. L'égalité de from et password dans ce cas n'est en réalité qu'un effet secondaire de ne pas être nul.
jimm101
1
@ jimm101 Oui, je pouvais voir que c'était un problème. L'avantage en termes de performances serait minime / non détectable pour une solution plus détaillée. Je ne sais pas si c'est le problème. Je vais le mettre à jour.
mat du
2
@matt Il n'y a peut-être pas d'avantage en termes de performances - on ne sait pas ce que le compilateur ferait, et ce que la puce tirerait de la mémoire dans ce cas. De nombreux cycles de programmeurs peuvent être gravés sur des optimisations qui ne donnent vraiment rien.
jimm101
6

Voici un moyen relativement simple qui n'implique aucun Xor og long ifs. Cependant, cela vous oblige à être un peu plus détaillé, mais vous pouvez utiliser les exceptions personnalisées que j'ai suggérées pour obtenir un message d'erreur plus significatif.

private void validatePasswordExists(Parameters params) {
   if (!params.hasKey("password")){
      throw new PasswordMissingException("Password missing");
   }
}

private void validateFromExists(Parameters params) {
   if (!params.hasKey("from")){
      throw new FromEmailMissingException("From-email missing");
   }
}

private void validateParams(Parameters params) {

  if (params.hasKey("from") || params.hasKey("password")){
     validateFromExists(params);
     validatePasswordExists(params);
  }
}
Arnab Datta
la source
1
vous ne devez pas utiliser d'exceptions à la place d'une instruction de flux de contrôle. En plus d'être un impact négatif sur les performances, cela diminue surtout la lisibilité de votre code car il rompt le flux mental.
un phu
1
@anphu Non. Non. L'utilisation d'exceptions augmente la lisibilité du code car elle supprime les clauses if-else et rend le flux de code plus clair. docs.oracle.com/javase/tutorial/essential/exceptions/…
Arnab Datta
1
Je pense que vous confondez quelque chose de vraiment exceptionnel par rapport à quelque chose qui se produit régulièrement et qui pourrait être considéré comme faisant partie d'une exécution normale. La doc java utilise des exemples exceptionnels c'est-à-dire manque de mémoire lors de la lecture d'un fichier; La rencontre de paramètres invalides n'est pas exceptionnelle. "N'utilisez pas d'exceptions pour le flux normal de contrôle." - blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
un phu
Eh bien, d'abord: si les arguments manquants / appropriés ne sont pas exceptionnels, pourquoi l'exception IllegalArgumentException existe-t-elle alors? Deuxièmement: si vous pensez vraiment que les arguments invalides ne sont pas exceptionnels, il ne devrait pas non plus y avoir de validation. En d'autres termes, essayez simplement de faire l'action et lorsque quelque chose ne va pas, lancez une exception. Cette approche est très bien, mais la pénalité de performance dont vous parlez est encourue ici, pas dans l'approche que j'ai suggérée. Les exceptions Java ne sont pas lentes lorsqu'elles sont lancées; c'est le stacktrace qui prend du temps à récupérer.
Arnab Datta
Le contexte est essentiel. Dans le contexte d'OP (application sendmail), oublier le nom d'utilisateur et le mot de passe est courant et attendu. Dans un algorithme de guidage de missile, un paramètre de coordonnée nul devrait lever une exception. Je n'ai pas dit de ne pas valider les paramètres. Dans le contexte d'OP, j'ai dit de ne pas utiliser d'exception pour piloter la logique de l'application. Dérouler le stacktrace est le coup de performance dont je parle. En utilisant votre approche, vous finirez par attraper l'exception PasswordMissingException / FromEmailMissingException, c'est-à-dire vous détendre, ou pire, la laisser sans gestion. .
un phu
6

Personne ne semble avoir mentionné l' opérateur ternaire :

if (a==null? b!=null:b==null)

Fonctionne bien pour vérifier cette condition particulière, mais ne généralise pas bien au-delà de deux variables.

gbronner
la source
1
A l' air bien, mais plus difficile à comprendre que ^, !=avec deux bools ou deux ifs
CoolGuy
@coolguy Je suppose que l'opérateur ternaire est beaucoup plus courant que l'opérateur XOR (sans parler de la `` surprise mentale '' chaque fois que vous voyez XOR dans un code qui ne fait pas d'opérations sur les bits), et cette formulation a tendance à éviter la coupure et collez les erreurs qui affligent le double if.
gbronner
Non recommandé. Cela ne fera pas la différence entre (a! = Null && b == null) et (a == null && b! = Null). Si vous comptez utiliser l'opérateur ternaire:a == null ? (b == null? "both null" : "a null while b is not") : (b ==null? "b null while a is not")
Arnab Datta
5

Comme je vois vos intentions, il n'est pas nécessaire de toujours vérifier les deux nullités exclusives mais de vérifier si passwordest nul si et seulement si fromn'est pas nul. Vous pouvez ignorer l' passwordargument donné et utiliser votre propre valeur par défaut si fromest null.

Écrit en pseudo doit être comme ceci:

if (from == null) { // form is null, ignore given password here
    // use your own defaults
} else if (password == null) { // form is given but password is not
    // throw exception
} else { // both arguments are given
    // use given arguments
}
JordiVilaplana
la source
4
Le seul problème avec ceci est que lorsque l'utilisateur fournit passwordsans fournir from, il peut avoir l'intention de remplacer le mot de passe, mais conserver le compte par défaut. Si l'utilisateur fait cela, c'est une instruction invalide et il doit en être informé. Le programme ne doit pas continuer comme si l'entrée était valide, et essayer d'utiliser le compte par défaut avec un mot de passe que l'utilisateur n'a pas spécifié. Je jure sur des programmes comme ça.
David Bullock
4

Je suis surpris que personne n'ait mentionné la solution simple de créer fromet de passwordchamps d'une classe et de passer une référence à une instance de cette classe:

class Account {
    final String name, password;
    Account(String name, String password) {
        this.name = Objects.requireNonNull(name, "name");
        this.password = Objects.requireNonNull(password, "password");
    }
}

// the code that requires an account
Account from;
// do stuff

Ici frompeut être nul ou non nul et s'il n'est pas nul, ses deux champs ont des valeurs non nulles.

Un avantage de cette approche est que l'erreur de rendre un champ mais pas l'autre champ nul est déclenchée là où le compte est initialement obtenu, pas lorsque le code utilisant le compte s'exécute. Au moment où le code utilisant le compte est exécuté, il est impossible que les données soient invalides.

Un autre avantage de cette approche est plus lisible car elle fournit plus d'informations sémantiques. En outre, il est probable que vous ayez besoin du nom et du mot de passe ensemble à d'autres endroits, de sorte que le coût de la définition d'une classe supplémentaire s'amortit sur plusieurs utilisations.

Réintégrer Monica
la source
Cela ne fonctionne pas comme prévu car il new Account(null, null)lancera un NPE même si un compte avec à la fois un nom nul et un mot de passe est toujours valide.
HieuHT
L'idée est de passer null si le nom et le mot de passe sont nuls, que vous disiez ou non dans le monde réel que le compte existe.
Réintégrer Monica
Ce que j'obtiens d'OP, c'est que soit les deux sont non nuls, soit les deux sont nuls. Je me demandais simplement comment créer un objet Account avec à la fois le nom et le mot de passe null?
HieuHT
@HieuHT Désolé, mon dernier commentaire n'était pas clair. Si le nom et le mot de passe sont nuls, vous utiliserez à la nullplace d'un Account. Vous ne passeriez pas nullau Accountconstructeur.
Réintègre Monica