Cómo usar nulo en el interruptor

6 minutos de lectura

avatar de usuario
hudi

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

En el código anterior, no puedo usar nulo en la declaración de cambio de caso. ¿Cómo puedo hacer esto de manera diferente? no puedo usar default porque entonces quiero hacer otra cosa.

  • antes de cambiar verifique la condición nula if(i==null) {//dosomething}

    – Nagaraju Badaeni

    26 de abril de 2012 a las 11:09


  • Esto realmente haría que el cambio fuera útil. Otros lenguajes de coincidencia de patrones funcionan de esta manera.

    – Pirolístico

    24/06/2014 a las 16:35

avatar de usuario
Jesper

Esto no es posible con un switch declaración en Java. Comprobar null antes de switch:

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

No puedes usar objetos arbitrarios en switch declaraciones*. La razón por la que el compilador no se queja switch (i) dónde i es un Integer es porque Java desempaca automáticamente el Integer a una int. Como ya dijo assylias, el unboxing arrojará un NullPointerException cuando i es null.

* Desde Java 7 puedes usar String en switch declaraciones.

Más sobre switch (incluyendo ejemplo con variable nula) en Documentos de Oracle – Cambiar

  • También puede usar enumeraciones en sentencias de cambio.

    – joriki

    29 de marzo de 2013 a las 18:23

  • Tiene sentido que no pueda usar un entero nulo u otra clase de contenedor debido al desempaquetado. Pero, ¿qué pasa con las enumeraciones y las cadenas? ¿Por qué no pueden ser nulos?

    – Luan Nico

    2 de noviembre de 2013 a las 11:20

  • No entiendo por qué un cortocircuito de nulo asignado al caso “predeterminado” o un caso especial para un interruptor nulo no se implementó para Strings. Hace que el uso de interruptores para simplificar el código no tenga sentido, ya que siempre tiene que hacer una verificación nula. Sin embargo, no estoy diciendo que la simplificación sea el único uso para los interruptores.

    – Reimio

    26 de junio de 2014 a las 18:36


  • @Reimius, no siempre tiene que hacer una verificación nula. Si respeta los contratos de código que le da a sus métodos, casi siempre puede lograr no tener su código abarrotado de cheques nulos. Sin embargo, usar afirmaciones siempre es bueno.

    – Joffrey

    18 mayo 2015 a las 22:46


  • También me gustaría saber la respuesta a la consulta de @LuanNico. Parece irrazonable que null no puede ser un caso válido cuando se trabaja con String y enum tipos Quizás el enum la implementación se basa en llamar ordinal() detrás de escena (aunque aun así, ¿por qué no tratar null como teniendo un ‘ordinal’ de -1?), y el String la versión hace algo usando intern() y la comparación de punteros (o de lo contrario se basa en algo que requiere estrictamente eliminar la referencia de un objeto)?

    – aroth

    10 de agosto de 2016 a las 2:29


switch ((i != null) ? i : DEFAULT_VALUE) {
        //...
}

  • forma más limpia que usar un extra if else

    – Vivek Agrawal

    15 de noviembre de 2019 a las 10:28

  • Para Groovy, puedes usar switch (i ?: DEFAULT_VALUE)

    – Tony

    27 de mayo a las 5:54


avatar de usuario
asilias

switch(i) lanzará una NullPointerException si i es nullporque intentará desempaquetar el Integer en una int. Asi que case nullque resulta ser ilegal, nunca se habría alcanzado de todos modos.

Debe verificar que i no sea nulo antes del switch declaración.

Java docs establece claramente que:

La prohibición de usar nulo como etiqueta de cambio evita que se escriba código que nunca se pueda ejecutar. Si la expresión de cambio es de un tipo de referencia, como un tipo primitivo encuadrado o una enumeración, se producirá un error de tiempo de ejecución si la expresión se evalúa como nula en tiempo de ejecución.

Debe tener que verificar nulo antes de la ejecución de la instrucción Swithch.

if (i == null)

Ver La declaración del cambio

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

Dado:

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

Para mí, esto generalmente se alinea con una tabla de búsqueda en una base de datos (solo para tablas que rara vez se actualizan).

Sin embargo, cuando trato de usar findByTypeId en una declaración de cambio (desde, muy probablemente, la entrada del usuario)…

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

…como han dicho otros, esto da como resultado una NPE @ switch(personType) {. Una solución alternativa (es decir, “solución”) que comencé a implementar fue agregar un UNKNOWN(-1) escribe.

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

Ahora, no tiene que hacer una verificación nula donde cuenta y puede elegir manejar o no UNKNOWN tipos (NOTA: -1 es un identificador poco probable en un escenario comercial, pero obviamente elija algo que tenga sentido para su caso de uso).

  • UNKNOWN es la mejor solución que he visto en esto y supera los controles nulos.

    – sonido de los miembros

    26 de febrero de 2016 a las 12:51

avatar de usuario
kai

tienes que hacer un

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

  • UNKNOWN es la mejor solución que he visto en esto y supera los controles nulos.

    – sonido de los miembros

    26 de febrero de 2016 a las 12:51

avatar de usuario
albahaca bourque

Coincidencia de patrones con switch

El comportamiento nulo de las declaraciones de cambio está a punto de cambiar con la adición de la coincidencia de patrones (que tiene avance estado en JDK 17/18/19)

Cambios de patrón y nulo

Tradicionalmente, las sentencias de cambio y las expresiones lanzan
NullPointerException si la expresión del selector se evalúa como nullpor lo que la prueba de null debe hacerse fuera del interruptor.

[…]

Esto era razonable cuando Switch admitía solo unos pocos tipos de referencia. Sin embargo, si switch permite una expresión de selector de cualquier tipo, y las etiquetas de casos pueden tener patrones de tipo, entonces la prueba nula independiente se siente como una distinción arbitraria e invita a una repetición innecesaria y a una oportunidad de error. Sería mejor integrar la prueba nula en el interruptor permitiendo una nueva etiqueta de caso nulo.

Ver JEP 427: Coincidencia de patrones para interruptor (Tercera versión preliminar)

Esto significa básicamente que Ud. pueden simplemente escribe

switch (null) {
case null: ...
}

pero si omites el case null:-parte, el interruptor todavía lanzará un NullPointerException

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad