web-dev-qa-db-fra.com

Comment vérifier la nullité de plusieurs objets?

Souvent, je peux voir des constructions de code comme suit:

if(a == null || b == null || c == null){
    //...
}

Je me demande s'il existe une bibliothèque largement utilisée (Google, Apache, etc.) pour vérifier la nullité de plusieurs objets à la fois, par exemple:

if(anyIsNull(a, b, c)){
    //...
}

ou

if(allAreNulls(a, b, c)){
    //...
}

MISE À JOUR:

  1. Je sais parfaitement comment l'écrire moi-même
  2. Je sais que cela peut être le résultat de la mauvaise structure du programme, mais ce n'est pas le cas ici
  3. Rendons les choses plus difficiles et remplaçons l'exemple original par quelque chose comme ceci:

    if(a != null && a.getFoo() != null && a.getFoo().getBar() != null){
        //...
    }
    

MISE À JOUR 2:

J'ai créé une demande d'extraction pour la bibliothèque Apache Commons Lang pour corriger cet écart:

Ceux-ci seront incorporés dans commons-lang, version 3.5:

  • anyNotNull (Object... values)
  • allNotNull (Object... values)
42
Krzysztof Wolny

EDIT 2018: Depuis Apache Commons lang 3.5, il y a eu ObjectUtils.allNotNull() et ObjectUtils.anyNotNull() .


Non.

Aucun Apache Commons Lang (3.4) , Google Guava (18) et Spring (4.1.7) ne fournit pas une telle méthode utilitaire.

Vous devrez l'écrire vous-même si vous en avez vraiment, vraiment besoin. Dans le moderne Java, je considérerais probablement la nécessité d'une telle construction comme une odeur de code, cependant.

24
Petr Janeček

Dans Java 8, vous pouvez utiliser Stream.allMatch pour vérifier si toutes les valeurs correspondent à une certaine condition, telle que null Pas beaucoup plus court, mais peut-être un peu plus facile à lire.

if (Stream.of(a, b, c).allMatch(x -> x == null)) {
    ...
}

Et de manière analogue pour anyMatch et noneMatch.


À propos de votre "exemple le plus difficile": dans ce cas, je pense qu'il n'y a aucun moyen d'écrire une conjonction de vérification nulle paresseuse, comme celle que vous avez:

if (a != null && a.getFoo() != null && a.getFoo().getBar() != null) {
    ...
}

L'une des autres approches, utilisant des flux, des listes ou des méthodes var-arg, essaierait d'évaluer a.getFoo() avant que a ait été testé pour ne pas être null. Vous pouvez utiliser Optional avec map et des pointeurs de méthode, qui seront évalués paresseusement les uns après les autres, mais la possibilité de les rendre plus lisibles est discutable et peut varier d'un cas à l'autre (en particulier pour noms de classe plus longs):

if (Optional.ofNullable(a).map(A::getFoo).map(B::getBar).isPresent()) {
    ...
}

Bar bar = Optional.ofNullable(a).map(A::getFoo).map(B::getBar).orElse(null);

Une autre alternative pourrait être de try pour accéder à l'élément le plus intérieur, mais j'ai le sentiment que cela n'est pas considéré comme une bonne pratique non plus:

try {
    Bar bar = a.getFoo().getBar();
    ...
catch (NullPointerException e) {
    ...
}

En particulier, cela interceptera également tous les autres NPE après accès à cet élément - soit cela, soit vous devez mettre uniquement le Bar bar = ... Dans le try et tout le reste dans un autre bloc if après le try, annulant tout gain (discutable) de lisibilité ou de concision.

(Je me souviens vaguement de quelque chose à propos d'une notation comme a?.getFoo()?.getBar() != null, mais je ne me souviens pas si c'était une demande de fonctionnalité pour Java ou un langage entièrement différent.)

36
tobias_k

Vous pouvez également utiliser quelque chose comme la méthode suivante. Il vous permet de passer autant de paramètres que vous le souhaitez:

public static boolean isAnyObjectNull(Object... objects) {
    for (Object o: objects) {
        if (o == null) {
            return true;
        }
    }
    return false;
}

Vous l'appelez avec autant de paramètres que vous le souhaitez:

isAnyObjectNull(a, b, c, d, e, f);

Vous pouvez faire quelque chose de similaire pour areAllNull.

public static boolean areAllObjectsNull(Object... objects) {
    for (Object o: objects) {
        if (o != null) {
            return false;
        }
    }
    return true;
}

Note: vous pouvez également utiliser l'opérateur ternaire au lieu de if (o == null). Les deux méthodes présentées ici n'ont aucune gestion d'erreur. Adaptez-le à vos besoins.

12
kamwo

C'est possible avec l'aide de la classe Objects

public static void requireNonNull(Object... objects) {
    for (Object object : objects) {
        Objects.requireNonNull(object);
    }
}
1
viavad

Vous pouvez créer une liste de vos objets et y utiliser yourList.contains(null).

List < Object > obList = new ArrayList < Object > ();

String a = null;
Integer b = 2;
Character c = '9';

obList.add(a);
obList.add(b);
obList.add(c);

System.out.println("List is " + obList);

if (obList.contains(null)) {
    System.out.println("contains null");
} else {
    System.out.println("does not contains null");
}

[~ # ~] démo [~ # ~]

0
singhakash