web-dev-qa-db-fra.com

Comment utiliser null dans switch

Integer i = ...

switch (i){
    case null:
        doSomething0();
        break;    
    }

Dans le code ci-dessus, je ne peux pas utiliser la valeur null dans l'instruction switch case. Comment puis-je faire cela différemment? Je ne peux pas utiliser default car je veux faire autre chose.

162
hudi

Ce n'est pas possible avec une instruction switch en Java. Vérifiez la null avant la switch:

if (i == null) {
    doSomething0();
} else {
    switch (i) {
    case 1:
        // ...
        break;
    }
}

Vous ne pouvez pas utiliser d'objets arbitraires dans les instructions switch*. La raison pour laquelle le compilateur ne se plaint pas de switch (i)i est une Integer est parce que Java décompresse automatiquement la Integer en int. Comme déjà dit assylias, le déballage lancera une NullPointerException lorsque i est null.

* Depuis Java 7, vous pouvez utiliser String dans les instructions switch.

En savoir plus sur switch (avec un exemple avec une variable null) dans Oracle Docs - Switch

231
Jesper
switch ((i != null) ? i : DEFAULT_VALUE) {
        //...
}
68
tetsuo

switch(i) lève une exception NullPointerException si i est null, car il essaiera de décompresser la Integer dans une int Donc, case null, qui s'avère illégal, n'aurait jamais été atteint de toute façon.

Vous devez vérifier que i n'est pas null avant l'instruction switch.

32
assylias

La documentation Java a clairement indiqué que:

L'interdiction d'utiliser null comme étiquette de commutateur empêche d'écrire du code qui ne peut jamais être exécuté. Si l'expression de commutateur est d'un type de référence, tel qu'un type de primitive encadré ou une énumération, une erreur d'exécution se produira si l'expression est évaluée à null au moment de l'exécution.

Vous devez avoir vérifier la valeur null avant l'exécution de l'instruction Swithch. 

if (i == null)

Voir The Switch Statement

case null: // will never be executed, therefore disallowed.
19
Shehzad

Donné:

public enum PersonType {
    COOL_GUY(1),
    JERK(2);

    private final int typeId;
    private PersonType(int typeId) {
        this.typeId = typeId;
    }

    public final int getTypeId() {
        return typeId;
    }

    public static PersonType findByTypeId(int typeId) {
        for (PersonType type : values()) {
            if (type.typeId == typeId) {
                return type;
            }
        }
        return null;
    }
}

Pour moi, cela correspond généralement à une table de consultation dans une base de données (pour les tables rarement mises à jour).

Cependant, lorsque j'essaie d'utiliser findByTypeId dans une instruction switch (de, probablement, entrée de l'utilisateur) ...

int userInput = 3;
PersonType personType = PersonType.findByTypeId(userInput);
switch(personType) {
case COOL_GUY:
    // Do things only a cool guy would do.
    break;
case JERK:
    // Push back. Don't enable him.
    break;
default:
    // I don't know or care what to do with this mess.
}

... comme d'autres l'ont indiqué, cela donne un NPE @ switch(personType) {. Une solution (c’est-à-dire une "solution") que j’ai commencé à implémenter consistait à ajouter un type UNKNOWN(-1).

public enum PersonType {
    UNKNOWN(-1),
    COOL_GUY(1),
    JERK(2);
    ...
    public static PersonType findByTypeId(int id) {
        ...
        return UNKNOWN;
    }
}

Désormais, vous n'avez pas à vérifier les valeurs NULL là où cela compte et vous pouvez choisir ou non de gérer les types UNKNOWN. (REMARQUE: -1 est un identifiant improbable dans un scénario commercial, mais choisissez bien évidemment quelque chose de logique pour votre cas d'utilisation).

12
Beez

Vous devez faire un 

if (i == null) {
   doSomething0();
} else {
   switch (i) {
   }
}
6
Kai

Certaines bibliothèques tentent d’offrir des alternatives à l’instruction Java switch intégrée. Vavr est l'un d'entre eux, ils le généralisent au filtrage par motif.

Voici un exemple tiré de leur documentation :

String s = Match(i).of(
    Case($(1), "one"),
    Case($(2), "two"),
    Case($(), "?")
);

Vous pouvez utiliser n’importe quel prédicat, mais ils sont nombreux à être prêts à l'emploi et $(null) est parfaitement légal. Je trouve cette solution plus élégante que les alternatives, mais cela nécessite Java8 et une dépendance à la bibliothèque vavr ...

4
Emmanuel Touzery

commutateur (String.valueOf (valeur)) { case "null": défaut: }

0
l0v3

Voyez comment le SWITCH pourrait fonctionner,

  • en cas de primitives, nous savons que cela peut échouer avec NPE pour l'auto-boxing
  • mais pour String ou enum, il peut s'agir de la méthode equals, qui nécessite évidemment une valeur LHS sur laquelle equals est appelé. Ainsi, étant donné qu'aucune méthode ne peut être invoquée sur un null, un commutateur ne peut pas gérer null.
0
Puneet

Vous pouvez également utiliser String.valueOf((Object) nullableString) Comme

switch (String.valueOf((Object) nullableString)) {
case "someCase"
    //...
    break;
...
case "null": // or default:
    //...
        break;
}

Voir intéressant SO Q/A: Pourquoi String.valueOf (null) lève une exception NullPointerException

0
oikonomopo

Tu ne peux pas. Vous pouvez utiliser les primitives (int, char, short, byte) et String (Strings en Java 7 uniquement) dans switch. les primitives ne peuvent pas être nulles.
Vérifier i séparément avant de passer à l’interrupteur.

0
Nikita Beloglazov