Compruebe si nulo booleano es verdadero resultados en excepción

169

Tengo el siguiente código:

Boolean bool = null;

try 
{
    if (bool)
    {
        //DoSomething
    }                   
} 
catch (Exception e) 
{
    System.out.println(e.getMessage());             
}

¿Por qué mi chequeo en la variable booleana "bool" resulta en una excepción? ¿No debería simplemente saltar más allá de la declaración if cuando "ve" que no es cierto? Cuando elimino la declaración if o verifico si NO es nula, la excepción desaparece.

Birdman
fuente
3
Las respuestas anteriores sobre unboxing de objetos son correctas. Sin embargo, por razones de integridad, también puede cambiar su código para usar el primitivo "booleano" en lugar del contenedor de objetos "booleano". También debe actualizarse sobre la diferencia entre un primitivo y un objeto.
Marvo
Mientras tanto ... if (bool == Boolean.TRUE)evalúa falso sin generar una excepción. No estoy seguro si esto fue intencional en el caso que acabo de encontrar.
simon.watts
2
@ simon.watts que sería falso por boolser nullOR si Booleanse construyera explícitamente (y no como referencia Boolean.TRUE). Entonces no recomendado; a diferencia de if (Boolean.TRUE.equals(bool))lo que funcionaría como se esperaba, incluido el manejo seguro del nullvalor.
StaxMan

Respuestas:

171

Cuando tienes un booleanpuede ser trueo false. Sin embargo, cuando tienes un Booleanpuede ser cualquiera Boolean.TRUE, Boolean.FALSEo nullcomo cualquier otro objeto.

En su caso particular, su instrucción Booleanis nully la ifdesencadena una conversión implícita a la booleanque produce el NullPointerException. Es posible que necesite en su lugar:

if(bool != null && bool) { ... }
K-Ballo
fuente
23
Técnicamente, a Booleanpuede ser cualquier número de instancias verdaderas, no solo Boolean.TRUE. Por ejemplo new Boolean(true).
Steve Kuo
1
Me cuesta entender por qué if (myBoolean)(dónde myBooleanestá Boolean) no genera un error del compilador o al menos una advertencia. Este es un problema seguro.
Josh M.
1
@JoshM. Esto se debe a que Java realiza el encajonamiento y desempaquetado de envoltorios: docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Vinicius
3
@Vinicius seguro, pero el compilador debe hacer lo nulo por nosotros en este caso, al menos a través de una advertencia del compilador.
Josh M.
2
@JoshM. No puedo estar más de acuerdo :)
Vinicius
402

Si no le gustan los cheques nulos adicionales:

if (Boolean.TRUE.equals(value)) {...}
AvrDragon
fuente
1
@AvrDragon: ¿se requiere igual? Operador == funciona aquí ya que el booleano solo tiene dos valores
Atul el
77
@ Atul Sí, se requiere igual aquí. Porque (new Boolean (true) == new Boolean (true)) es ... falso. Motivo: Boolean es solo una clase y puede tener múltiples instancias como cualquier otra clase en Java.
AvrDragon
35
Sí, eso es una lástima, el constructor debe ser privada por lo que ha asegurado que se trata de un twingleton ...
FORTRAN
15
@fortran +1 para "twingleton".
Bennett McElwee
1
No tiene absolutamente ningún sentido usar Apache BooleanUtils sobre este idioma.
StaxMan
82

Utilice los Apache BooleanUtils .

(Si el rendimiento máximo es la prioridad más importante en su proyecto, busque una de las otras respuestas para una solución nativa que no requiera incluir una biblioteca externa).

No reinventes la rueda. Aproveche lo que ya se ha construido y use isTrue():

BooleanUtils.isTrue( bool );

Comprueba si un Booleanvalor es verdadero, manejándolo nullregresando false.

Si no está limitado a las bibliotecas que está "permitido" incluir, hay un montón de excelentes funciones auxiliares para todo tipo de casos de uso, incluidos Booleansy Strings. Le sugiero que lea detenidamente las diversas bibliotecas de Apache y vea lo que ya ofrecen.

Joshua Pinter
fuente
59
Reinventar la rueda no parece tan malo cuando la alternativa es usar una biblioteca externa para algo tan básico como esto.
Paul Manta
3
@PaulManta Estoy de acuerdo si esta es la única cosa que le nunca utiliza en las bibliotecas Apache Utils, pero la idea sugerida es la de "hojear" las bibliotecas exponerse a otras funciones útiles.
Joshua Pinter
1
Hay una penalización de rendimiento por usar estas bibliotecas. Entonces, para cosas tan básicas que son parte del lenguaje, no debe usar bibliotecas.
ACV
66
Esa biblioteca está reinventando la rueda. Intento evitar tales bibliotecas tanto como sea posible.
mschonaker
3
@mschonaker Si Apache BooleanUtils está reinventando la rueda, ¿cuál es la rueda original ? La idea es evitar crear un montón de funciones auxiliares que imiten lo que ya se ha hecho en bibliotecas como esta. También uso toStringYesNode esta biblioteca en todas mis aplicaciones.
Joshua Pinter
13

Booleantipos pueden ser null. Debe hacer una nullcomprobación tal como la configuró null.

if (bool != null && bool)
{
  //DoSomething
}                   
fastcodejava
fuente
3
¿Qué hay de malo en esta respuesta? No es la comprobación del bool lo que arrojaría la excepción. Votos negativos innecesarios.
dodexahedron
2
Estoy de acuerdo en que es una respuesta perfectamente razonable. Sin embargo, podría deshacerse del manejo de excepciones.
Marvo
14
La entrega de excepciones es innecesaria, y además se está haciendo de una manera que es un mal ejemplo para los principiantes. Esto merece un voto negativo, OMI. (Sí ... Sé que proviene del código de ejemplo, pero repetirlo en la Respuesta parece respaldarlo)
Stephen C
1
¿Cuál es el camino CORRECTO entonces? No veo tu respuesta aquí.
Marvo
55
La forma correcta es la de arriba ... sin manejo de excepciones. Además, el manejo de excepciones es demasiado general y no se recomienda.
vellvisher
8

O con el poder de Java 8 Opcional, también puedes hacer ese truco:

Optional.ofNullable(boolValue).orElse(false)

:)

provisota
fuente
5

Boolean es la clase de contenedor de objetos para el booleano primitivo. Esta clase, como cualquier clase, puede ser nula. Por razones de rendimiento y memoria, siempre es mejor usar el primitivo.

Las clases de contenedor en la API de Java tienen dos propósitos principales:

  1. Proporcionar un mecanismo para "ajustar" los valores primitivos en un objeto de modo que las primitivas puedan incluirse en actividades reservadas para objetos, como agregarse a Colecciones o devolverse desde un método con un valor de retorno de objeto.
  2. Proporcionar una variedad de funciones de utilidad para primitivas. La mayoría de estas funciones están relacionadas con varias conversiones: conversión de primitivas hacia y desde objetos String, y conversión de primitivas y objetos String hacia y desde diferentes bases (o radix), como binarias, octales y hexadecimales.

http://en.wikipedia.org/wiki/Primitive_wrapper_class

Orlan
fuente
0

Como su variable bool apunta a un valor nulo, siempre obtendrá una NullPointerException, primero debe inicializar la variable en algún lugar con un valor no nulo y luego modificarla.

RicardoE
fuente
1
Si fuera solo eso, el catchbloque manejaría la NullPointerException. El problema aquí es que el OP intenta desempaquetar una referencia nula en una primitiva.
Mike Adler
"siempre lo harás" : no siempre, excepto el código simplificado de muestra que no hace nada entre inicializar la variable nully luego probarla. Presumiblemente, el código real no sería tan simple o toda la ifprueba podría eliminarse.
nnnnnn