Me pregunto por qué la switch
declaración de Java 7 no admite un null
caso y en su lugar arroja NullPointerException
. Vea la línea comentada a continuación (ejemplo tomado del artículo de Tutoriales de Java enswitch
):
{
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;
}
Esto habría evitado una if
condición de verificación nula antes de cada switch
uso.
java
switch-statement
language-design
Prashant Bhate
fuente
fuente
null
causará una excepción. Realice unaif
verificación paranull
, luego vaya a laswitch
declaración.NullPointerException
si la expresión se evalúa comonull
en tiempo de ejecución] es un mejor resultado que omitir silenciosamente toda la declaración del interruptor o elegir ejecutar las declaraciones (si las hay) después del etiqueta predeterminada (si existe).Respuestas:
Como damryfbfnetsi señala en los comentarios, JLS §14.11 tiene la siguiente nota:
(énfasis mío)
Si bien la última oración omite la posibilidad de usar
case null:
, parece razonable y ofrece una visión de las intenciones de los diseñadores de idiomas.Si preferimos ver los detalles de implementación, esta publicación de blog de Christian Hujer tiene algunas especulaciones perspicaces sobre por qué
null
no está permitido en los switches (aunque se centra en elenum
switch en lugar delString
switch):Si bien los
String
conmutadores se implementan de manera diferente , elenum
conmutador vino primero y sentó el precedente de cómo debe comportarse el encendido de un tipo de referencia cuando la referencia esnull
.fuente
case null:
si se hubiera implementado exclusivamenteString
. Actualmente, todas lasString
comprobaciones requieren una comprobación nula de todos modos si queremos hacerlo correctamente, aunque principalmente implícitamente colocando la cadena constante primero como en"123test".equals(value)
. Ahora nos vemos obligados a escribir nuestra sentencia switch como enif (value != null) switch (value) {...
En general
null
es desagradable de manejar; Quizás un mejor idioma pueda vivir sin élnull
.Su problema puede ser resuelto por
fuente
month
es una cadena vacía: esto la tratará de la misma manera que una cadena nula.No es bonito, pero le
String.valueOf()
permite usar una cadena nula en un interruptor. Si encuentranull
, lo convierte"null"
, de lo contrario, solo devuelve la misma cadena que le pasó. Si no lo maneja"null"
explícitamente, irá adefault
. La única advertencia es que no hay forma de distinguir entre la cadena"null"
y unanull
variable real .fuente
Este es un intento de responder por qué arroja
NullPointerException
El resultado del siguiente comando javap revela que
case
se elige en función del código hash de laswitch
cadena de argumento y, por lo tanto, arroja NPE cuando.hashCode()
se invoca en una cadena nula.Esto significa, en base a las respuestas a ¿Puede el código hash de Java producir el mismo valor para diferentes cadenas? , aunque es raro, todavía existe la posibilidad de que coincidan dos casos (dos cadenas con el mismo código hash). Vea este ejemplo a continuación
javap para el cual
Como puede ver, solo se genera un caso para
"Ea"
y"FB"
con dosif
condiciones para verificar una coincidencia con cada cadena de casos. ¡Una forma muy interesante y complicada de implementar esta funcionalidad!fuente
hashCode
devolver los mismos valores en diferentes ejecuciones de un programa, pero dado que los hash de cadena se convierten en ejecutables por el compilador, el método de hash de cadenas termina siendo parte de la especificación del lenguaje.Larga historia corta ... (¡y espero que sea lo suficientemente interesante!)
Enum se introdujo por primera vez en Java1.5 ( septiembre de 2004 ) y el error que solicitaba permitir el cambio de String se archivó hace mucho tiempo ( octubre de 1995 ). Si mira el comentario publicado sobre ese error en junio de 2004 , dice que
Don't hold your breath. Nothing resembling this is in our plans.
parece que aplazaron ( ignoraron ) este error y finalmente lanzaron Java 1.5 en el mismo año en que introdujeron 'enum' con ordinal comenzando en 0 y decidieron ( perdido ) para no admitir nulo para enumeración. Más tarde en Java1.7 ( julio de 2011 ) lo siguieron ( forzado) la misma filosofía con String (es decir, al generar el bytecode no se realizó ninguna comprobación nula antes de llamar al método hashcode ()).Así que creo que se reduce al hecho de que enum entró primero y se implementó con su ordinal comenzando en 0 debido a que no podían admitir el valor nulo en el bloque de interruptores y luego con String decidieron forzar la misma filosofía, es decir, el valor nulo no permitido en el bloque de interruptores.
TL; DR With String podrían haberse ocupado de NPE (causado por el intento de generar código hash para nulo) mientras implementaban la conversión de código java a byte pero finalmente decidieron no hacerlo.
Ref: TheBUG , JavaVersionHistory , JavaCodeToByteCode , SO
fuente
De acuerdo con Java Docs:
Como
null
no tiene ningún tipo y no es una instancia de nada, no funcionará con una instrucción switch.fuente
null
es un valor válido para unString
,Character
,Byte
,Short
, oInteger
de referencia.La respuesta es simplemente que si usa un interruptor con un tipo de referencia (como un tipo primitivo en caja), el error en tiempo de ejecución se producirá si la expresión es nula porque al desempaquetarla arrojaría el NPE.
entonces el caso nulo (que es ilegal) nunca podría ejecutarse de todos modos;)
fuente
if (x == null) { // the case: null part }
Estoy de acuerdo con los comentarios perspicaces (Under the hood ...) en https://stackoverflow.com/a/18263594/1053496 en la respuesta de @Paul Bellora.
Encontré una razón más de mi experiencia.
Si 'case' puede ser nulo, eso significa que switch (variable) es nulo, siempre que el desarrollador proporcione un caso 'nulo' coincidente, entonces podemos argumentar que está bien. Pero, ¿qué sucederá si el desarrollador no proporciona ningún caso 'nulo' coincidente? Luego tenemos que hacer coincidirlo con un caso 'predeterminado' que puede no ser lo que el desarrollador ha intentado manejar en el caso predeterminado. Por lo tanto, hacer coincidir 'nulo' con un valor predeterminado podría causar un 'comportamiento sorprendente'. Por lo tanto, lanzar 'NPE' hará que el desarrollador maneje todos los casos explícitamente. Encontré lanzar NPE en este caso muy reflexivo.
fuente
Utilice la clase Apache StringUtils
fuente