Me pregunto por qué la switchdeclaración de Java 7 no admite un nullcaso 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 ifcondición de verificación nula antes de cada switchuso.
java
switch-statement
language-design
Prashant Bhate
fuente
fuente

nullcausará una excepción. Realice unaifverificación paranull, luego vaya a laswitchdeclaración.NullPointerExceptionsi la expresión se evalúa comonullen 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é
nullno está permitido en los switches (aunque se centra en elenumswitch en lugar delStringswitch):Si bien los
Stringconmutadores se implementan de manera diferente , elenumconmutador 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 lasStringcomprobaciones 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
nulles desagradable de manejar; Quizás un mejor idioma pueda vivir sin élnull.Su problema puede ser resuelto por
fuente
monthes 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 unanullvariable real .fuente
Este es un intento de responder por qué arroja
NullPointerExceptionEl resultado del siguiente comando javap revela que
casese elige en función del código hash de laswitchcadena 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 dosifcondiciones para verificar una coincidencia con cada cadena de casos. ¡Una forma muy interesante y complicada de implementar esta funcionalidad!fuente
hashCodedevolver 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
nullno tiene ningún tipo y no es una instancia de nada, no funcionará con una instrucción switch.fuente
nulles un valor válido para unString,Character,Byte,Short, oIntegerde 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