Мне просто интересно, почему switch
оператор Java 7 не поддерживает null
регистр, а вместо этого бросает NullPointerException
? См. Прокомментированную строку ниже (пример взят из статьи Java Tutorialsswitch
):
{
String month = null;
switch (month) {
case "january":
monthNumber = 1;
break;
case "february":
monthNumber = 2;
break;
case "march":
monthNumber = 3;
break;
//case null:
default:
monthNumber = 0;
break;
}
return monthNumber;
}
Это позволило бы избежать if
условия проверки нуля перед каждым switch
использованием.
java
switch-statement
language-design
Прашант Бхате
источник
источник
null
вызовет исключение. Выполнитеif
проверкуnull
, а затем перейдите кswitch
выписке.NullPointerException
если выражение оценивается какnull
во время выполнения] - лучший результат, чем молчаливый пропуск всего оператора switch или выбор выполнения операторов (если есть) после метка по умолчанию (если есть).Ответы:
Как указывает damryfbfnetsi в комментариях, JLS §14.11 имеет следующее примечание:
(курсив мой)
Хотя последнее предложение пропускает возможность использования
case null:
, оно кажется разумным и дает представление о намерениях разработчиков языка.Если мы скорее посмотрим на детали реализации, в этом сообщении в блоге Кристиана Худжера есть некоторые проницательные предположения о том, почему
null
не разрешено в коммутаторах (хотя оно сосредоточено наenum
коммутаторе, а не наString
коммутаторе):Хотя
String
переключатели реализованы по-разному ,enum
переключатель появился первым и установил прецедент того, как включение ссылочного типа должно вести себя, когда ссылочный типnull
.источник
case null:
если бы она была реализована исключительно дляString
. В настоящее время для всехString
проверок в любом случае требуется проверка на null, если мы хотим сделать это правильно, хотя в большинстве случаев неявно, помещая сначала строковую константу, как в"123test".equals(value)
. Теперь мы вынуждены написать наш оператор switch как вif (value != null) switch (value) {...
Вообще
null
неприятно обращаться; возможно, лучший язык может жить безnull
.Ваша проблема может быть решена
источник
month
это пустая строка: это будет обрабатывать ее так же, как пустую строку.Это некрасиво, но
String.valueOf()
позволяет использовать в переключателе пустую строку. Если он находитnull
, он преобразует его в"null"
, в противном случае он просто возвращает ту же строку, которую вы ей передали. Если вы не обрабатываете"null"
явно, он перейдет вdefault
. Единственное предостережение заключается в том, что нет способа отличить String"null"
от фактическойnull
переменной.источник
Это попытка ответить, почему бросает
NullPointerException
Вывод команды javap ниже показывает, что
case
она выбрана на основе хэш- кодаswitch
строки аргумента и, следовательно, выдает NPE при.hashCode()
вызове с нулевой строкой.Это означает, что на основе ответов на вопрос, может ли хэш-код Java создавать одинаковое значение для разных строк? хотя и редко, все же существует вероятность совпадения двух случаев (две строки с одинаковым хэш-кодом). См. этот пример ниже
javap для которого
Как вы можете видеть, создается только один кейс для
"Ea"
и,"FB"
но с двумяif
условиями для проверки совпадения с каждой строкой кейса. Очень интересный и сложный способ реализации этого функционала!источник
hashCode
возврат одних и тех же значений при разных запусках программы, но поскольку строковые хэши запекаются в исполняемые файлы компилятор, метод хеширования строки становится частью спецификации языка.Короче ... (и, надеюсь, достаточно интересно !!!)
Enum были впервые представлены в Java1.5 ( сентябрь 2004 г. ), и ошибка, запрашивающая разрешение на включение String, была давно подана ( октябрь 1995 г. ). Если вы посмотрите на комментарий, опубликованный к этой ошибке в июне 2004 г. , он гласит: «
Don't hold your breath. Nothing resembling this is in our plans.
Похоже, они отложили ( проигнорировали ) эту ошибку и в конечном итоге запустили Java 1.5 в том же году, в котором они ввели enum с порядковым номером, начинающимся с 0, и решили ( пропущено ) не поддерживать null для enum. Позже в Java1.7 ( июль 2011 г. ) они последовали ( принудительно) та же философия со String (т.е. при генерации байт-кода перед вызовом метода hashcode () не выполнялась проверка на null).Итак, я думаю, что это сводится к тому факту, что enum пришло первым и было реализовано с его порядковым номером, начинающимся с 0, из-за чего они не могли поддерживать нулевое значение в блоке переключателя, а позже с помощью String они решили принудительно использовать ту же философию, то есть нулевое значение не разрешено в блоке переключателя.
TL; DR С помощью String они могли позаботиться о NPE (вызванном попыткой сгенерировать хэш-код для null) при реализации преобразования java-кода в преобразование байтового кода, но в конце концов решили не делать этого.
Ссылка: TheBUG , JavaVersionHistory , JavaCodeToByteCode , SO
источник
Согласно Java Docs:
Поскольку
null
не имеет типа и не является экземпляром чего-либо, он не будет работать с оператором switch.источник
null
является допустимым значением дляString
,Character
,Byte
,Short
, илиInteger
ссылки.Ответ прост: если вы используете переключатель со ссылочным типом (например, примитивный тип в штучной упаковке), ошибка времени выполнения возникнет, если выражение имеет значение NULL, потому что при его распаковке возникает NPE.
так что case null (что является незаконным) никогда не может быть выполнен;)
источник
if (x == null) { // the case: null part }
Я согласен с проницательными комментариями (Под капотом ....) в https://stackoverflow.com/a/18263594/1053496 в ответе @Paul Bellora.
Я нашел еще одну причину из своего опыта.
Если case может иметь значение null, это означает, что switch (переменная) имеет значение null, тогда, пока разработчик предоставляет соответствующий случай null, мы можем утверждать, что это нормально. Но что произойдет, если разработчик не предоставит ни одного подходящего «нулевого» случая. Затем мы должны сопоставить его со случаем «по умолчанию», который может быть не тем, что разработчик намеревался обработать в случае по умолчанию. Поэтому сопоставление «null» со значением по умолчанию может вызвать «неожиданное поведение». Поэтому использование NPE заставит разработчика обрабатывать все случаи явно. Я нашел бросание NPE в этом случае очень продуманным.
источник
Используйте класс Apache StringUtils
источник