Verifique se Booleano nulo é verdadeiro resulta em exceção

169

Eu tenho o seguinte código:

Boolean bool = null;

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

Por que meu check-in na variável booleana "bool" resulta em uma exceção? Não deveria simplesmente passar da declaração if quando "vê" que não é verdade? Quando removo a instrução if ou verifico se NÃO é nulo, a exceção desaparece.

homem Pássaro
fonte
3
As respostas acima sobre o desempacotamento de objetos estão corretas. Para fins de completude, no entanto, você também pode alterar seu código para usar o "booleano" primitivo em vez do wrapper de objeto "Boolean". Você também deve se atualizar sobre a diferença entre um primitivo e um objeto.
Marvo12
Enquanto isso ... if (bool == Boolean.TRUE)avalia false sem gerar uma exceção. Não tenho certeza se isso foi intencional no caso que acabei de encontrar.
simon.watts
2
@ simon.watts que seria falso por boolser nullOR se Booleanfosse construído explicitamente (e não como referência Boolean.TRUE). Então não é recomendado; ao contrário do if (Boolean.TRUE.equals(bool))que funcionaria conforme o esperado, incluindo manipulação segura de nullvalor.
StaxMan 21/02/19

Respostas:

171

Quando você tem um boolean, pode ser um trueou outro false. No entanto, quando você tem uma Booleanque pode ser Boolean.TRUE, Boolean.FALSEou nullcomo qualquer outro objeto.

No seu caso particular, você Booleané nulle a ifinstrução aciona uma conversão implícita para booleanque produz o NullPointerException. Você pode precisar:

if(bool != null && bool) { ... }
K-ballo
fonte
23
Tecnicamente, Booleanpode haver qualquer número de instâncias verdadeiras, não apenas Boolean.TRUE. Por exemplo new Boolean(true).
9788 Steve Kuo
1
Eu luto para entender por que if (myBoolean)(onde myBooleanestá Boolean) não gera um erro do compilador ou pelo menos um aviso. Este é um problema, com certeza.
Josh M.
1
@JoshM. Isso ocorre porque Java faz Boxing e Unboxing de wrappers: docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Vinicius
3
@ Vinicius claro, mas o compilador deve fazer o nulo para nós neste caso, através de um aviso do compilador, pelo menos.
Josh M.
2
@JoshM. Não posso concordar mais :)
Vinicius
402

Se você não gosta de verificações nulas extras:

if (Boolean.TRUE.equals(value)) {...}
AvrDragon
fonte
1
@AvrDragon: é igual a necessário? Operador == funciona aqui, pois o booleano possui apenas dois valores
Atul
7
@ Atul Sim, igual é necessário aqui. Porque (new Boolean (true) == new Boolean (true)) é .... false. Motivo: booleano é apenas uma classe e pode ter várias instâncias como qualquer outra classe em java.
AvrDragon
35
sim, isso é uma vergonha, o construtor deve ser privado por isso é garantido que é um twingleton ...
fortran
15
@fortran +1 para "twingleton".
Bennett McElwee
1
Não há absolutamente nenhum sentido em usar o Apache BooleanUtils sobre esse idioma.
StaxMan 21/02/19
82

Use o Apache BooleanUtils .

(Se o desempenho máximo for a prioridade mais importante em seu projeto, procure uma das outras respostas para uma solução nativa que não exija a inclusão de uma biblioteca externa.)

Não reinvente a roda. Aproveite o que já foi construído e use isTrue():

BooleanUtils.isTrue( bool );

Verifica se um Booleanvalor é verdadeiro, manipulando nullretornando false.

Se você não está limitado às bibliotecas que você "pode ​​incluir", há várias funções auxiliares excelentes para todos os tipos de casos de uso, incluindo Booleanse Strings. Eu sugiro que você examine as várias bibliotecas do Apache e veja o que elas já oferecem.

Joshua Pinter
fonte
59
Reinventar a roda não parece tão ruim quando a alternativa está usando uma biblioteca externa para algo tão básico quanto isso.
Paul Manta
3
@PaulManta Concordo, se esta é a única coisa que você nunca usar nas bibliotecas Apache Utils, mas a idéia sugerida é "peruse" as bibliotecas se expor a outras funções úteis.
Joshua Pinter
1
Há uma penalidade de desempenho por usar essas bibliotecas. Portanto, para coisas básicas que fazem parte da linguagem, você não deve usar bibliotecas.
ACV
6
Essa biblioteca está reinventando a roda. Tento evitar essas bibliotecas o máximo possível.
24515 mschonaker
3
@mschonaker Se o Apache BooleanUtils está reinventando a roda, qual é a roda original ? A idéia é evitar a criação de várias funções auxiliares que imitam o que já foi feito em bibliotecas como essa. Eu também uso toStringYesNodesta biblioteca em todos os meus aplicativos.
27515 Joshua Pinter
13

Booleantipos podem ser null. Você precisa fazer uma nullverificação como a definiu null.

if (bool != null && bool)
{
  //DoSomething
}                   
fastcodejava
fonte
3
O que há de errado com esta resposta? Não é a verificação do bool que lançaria a exceção. Votos negativos desnecessários.
dodexahedron
2
Concordo que é uma resposta perfeitamente razoável. Você pode se livrar do tratamento de exceções.
Marvo12
14
O tratamento de exceções é desnecessário e, além disso, está sendo realizado de uma maneira que é um mau exemplo para iniciantes. Isso merece um voto negativo, IMO. (Sim ... Eu sei que vem do código de exemplo, mas repeti-lo nos aparece resposta a endossá-lo.)
Stephen C
1
Qual é o caminho CERTO, então? Não vejo sua resposta aqui.
Marvo
5
O caminho certo é o descrito acima .. sem manipulação de exceção. Além disso, o tratamento de exceção é muito geral e é desencorajado.
vellvisher
8

Ou com o poder do Java 8 opcional, você também pode fazer esse truque:

Optional.ofNullable(boolValue).orElse(false)

:)

provisota
fonte
5

Boolean é a classe de wrapper de objeto para o booleano primitivo. Essa classe, como qualquer classe, pode de fato ser nula. Por motivos de desempenho e memória, é sempre melhor usar o primitivo.

As classes de wrapper na API Java servem a dois propósitos principais:

  1. Fornecer um mecanismo para "agrupar" valores primitivos em um objeto para que as primitivas possam ser incluídas em atividades reservadas a objetos, como sendo adicionadas a Coleções ou retornadas de um método com um valor de retorno de objeto.
  2. Fornecer uma variedade de funções de utilidade para primitivas. A maioria dessas funções está relacionada a várias conversões: converter primitivas para e de objetos String e converter primitivas e objetos String para e de diferentes bases (ou raiz), como binário, octal e hexadecimal.

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

Orlan
fonte
0

como sua variável bool está apontando para um nulo, você sempre obterá uma NullPointerException, precisará inicializar a variável primeiro em algum lugar com um valor não nulo e modificá-la.

RicardoE
fonte
1
Se fosse exatamente isso, o catchbloco manipularia a NullPointerException. O problema aqui é que o OP tenta desmarcar uma referência nula em uma primitiva.
Mike Adler
"você sempre" - nem sempre, exceto o exemplo, código simplificado que não faz nada entre inicializar a variável nulle testá-la. Presumivelmente, o código real não seria tão simples ou todo o ifteste poderia ser removido.
Nnnnnn