Вопрос по java, switch-statement – Как использовать нуль в switch

166
Integer i = ...

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

В приведенном выше коде я не могу использовать нуль в операторе switch case. Как я могу сделать это по-другому? Я не могу использоватьdefault потому что тогда я хочу сделать что-то еще.

Это фактически сделает переключение полезным. Другие языки сопоставления с образцом работают таким образом. Pyrolistical
перед переключением проверьте нулевое условие, если (i == null) {// dosomething} Nagaraju Badaeni

Ваш Ответ

10   ответов
19

Запрет на использование null в качестве метки переключателя не позволяет писать код, который никогда не будет выполнен. Если выражение-переключатель относится к ссылочному типу, такому как тип примитива в штучной упаковке или перечисление, произойдет ошибка времени выполнения, если выражение оценивается как ноль во время выполнения.

Перед выполнением оператора Swithch вы должны проверить наличие нуля.

if (i == null)

УвидетьЗаявление о переключении

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

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;
    }
}

Для меня это обычно совпадает с таблицей поиска в базе данных (только для редко обновляемых таблиц).

Тем не менее, когда я пытаюсь использоватьfindByTypeId в операторе switch (скорее всего, из пользовательского ввода) ...

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.
}

... как уже говорили другие, это приводит к NPE @switch(personType) {, Одним из обходных путей (т. Е. «Решение»), который я начал реализовывать, было добавлениеUNKNOWN(-1) тип.

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

Теперь вам не нужно выполнять нулевую проверку, где она имеет значение, и вы можете выбирать, обрабатывать или нетUNKNOWN типы. (НОТА:-1 является маловероятным идентификатором в бизнес-сценарии, но, очевидно, выберите то, что имеет смысл для вашего варианта использования).

UNKNOWN является лучшим решением по этому вопросу, которое я когда-либо видел, и проверяет нуль-проверки.
32

switch(i) сгенерирует исключение NullPointerException, если яnullпотому что он попытается распаковатьInteger вint, Такcase null, который оказывается незаконным, никогда бы не был достигнут в любом случае.

Вы должны проверить, что я не нулевой, прежде чемswitch заявление.

4

switch заявление.Vavr является одним из них, они обобщают это для сопоставления с образцом.

Вот пример изих документация:

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

Вы можете использовать любой предикат, но они предлагают многие из них из коробки, и$(null) совершенно законно. Я считаю, что это более элегантное решение, чем альтернативы, но для этого требуется java8 и зависимость от библиотеки vavr ...

0

Вы также можете использоватьString.valueOf((Object) nullableString) like

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

See interesting SO Q/A: Why does String.valueOf(null) throw a NullPointerException

232

switch заявление в Java. Проверитьnull передswitch:

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

Вы не можете использовать произвольные объекты вswitch заявления*, Причина, по которой компилятор не жалуетсяswitch (i) гдеi являетсяInteger потому что Java автоматически распаковываетInteger дляint, Как уже сказал Ассилиас, распаковкаNullPointerException когдаi являетсяnull.

* С Java 7 вы можете использоватьString вswitch заявления.

Больше оswitch (включая пример с нулевой переменной) вOracle Docs - Switch

Я также хотел бы знать ответ на запрос @ LuanNico. Кажется необоснованным, чтоnull не может быть действительным случаем при работе сString а такжеenum типы. Возможно,enum реализация опирается на вызовordinal() за кадром (хотя даже так, почему бы не лечитьnull как имеющий «порядковый» -1?), аString версия делает что-то, используяintern() и сравнение указателей (или иначе полагается на что-то, что строго требует разыменования объекта)?
Вы также можете использовать перечисления в выражениях switch.
@ Reimius Вы не всегда должны делать нулевую проверку. Если вы уважаете кодовые контракты, которые вы даете своим методам, вы почти всегда можетеnot ваш код загроможден нулевыми проверками. Использование утверждений всегда приятно.
Я не понимаю, почему короткое замыкание со значением NULL сопоставлено со значением «по умолчанию». Случай или особый случай для нулевого переключателя не был реализован для строк. Это делает использование ключей для упрощения кода бессмысленным, так как вы всегда должны делать нулевую проверку. Я не говорю, что упрощение является единственным использованием для переключателей, хотя.
Имеет смысл, что вы не можете использовать нулевое целое число или другой класс Wrapper из-за распаковки. Но как насчет перечислений и строк? Почему они не могут быть нулевыми?
0

case "null": default: }

0

char, short, byte) и String (только строки в Java 7) в переключателе. примитивы не могут быть нулевыми.
Проверьтеi в отдельном состоянии перед выключателем.

Вы также можете использовать перечисления.
если перечисление равно нулю, у вас возникнет та же проблема. Кстати, довольно странно, что switch не может обрабатывать ноль, поскольку у него есть предложение по умолчанию
@LeonardoKenji Предложение по умолчанию не имеет никакого отношения к null; что бы вы ни включали, оно будет разыменовано для проверки любых других случаев, поэтому предложение по умолчанию не будет обрабатывать нулевой случай (исключение NullPointerException выдается до того, как у него появится такая возможность).
Я думаю, он имел в виду, что предложение по умолчанию должно обрабатывать нуль, как любое другое возможное значение перечисления, которое не было перехвачено в предыдущем случае.
70

switch ((i != null) ? i : DEFAULT_VALUE) {
        //...
}
просто, прямо к делу
6

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

Похожие вопросы