检查null布尔值是否为true导致异常


169

我有以下代码:

Boolean bool = null;

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

为什么检查布尔变量“ bool”会导致异常?当它“看到”这不是事实时,它不应该跳过if语句吗? 当我删除if语句或检查它是否不为null时,该异常消失了。


3
上面有关对象拆箱的答案都是正确的。但是,出于完整性考虑,您还可以将代码更改为使用原始“ boolean”而不是对象包装“ Boolean”。您还应该刷新原始对象和对象之间的区别。
Marvo 2012年

同时... if (bool == Boolean.TRUE)评估为false而不产生异常。不知道在我刚刚发现的情况下这是否是故意的。
simon.watts

2
@ simon.watts 如果是显式构造的(而不是作为的引用),bool则为nullOR 会是错误的。所以不推荐;与之相反,它将按预期工作,包括安全地处理价值。BooleanBoolean.TRUEif (Boolean.TRUE.equals(bool))null
StaxMan '19

Answers:


171

当您拥有时,boolean它可以是truefalse。然而,当你有一个Boolean它可以是Boolean.TRUEBoolean.FALSEnull任何其他对象。

在您的特定情况下,您Boolean是is null并且该if语句触发对boolean产生的隐式转换NullPointerException。您可能需要:

if(bool != null && bool) { ... }

23
从技术上讲,a Boolean可以是任意数量的真实实例,而不仅仅是Boolean.TRUE。例如new Boolean(true)
Steve Kuo 2012年

1
我很难理解为什么if (myBoolean)(where myBooleanBoolean)不会引发编译器错误或至少没有警告。这肯定是一个陷阱。
乔什·M

1
@JoshM。这是因为Java会对包装程序进行装箱拆箱docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Vinicius

3
@Vinicius可以肯定,但是在这种情况下,编译器应该为我们做空,至少要通过编译器警告来执行。
Josh M.

2
@JoshM。不能完全同意:)
Vinicius

402

如果您不喜欢多余的null检查:

if (Boolean.TRUE.equals(value)) {...}

1
@AvrDragon:是否等于要求?运算符==在这里起作用,因为布尔值只有两个值
Atul

7
@Atul是的,这里等于。因为(new Boolean(true)== new Boolean(true))是.... 原因:布尔值只是一个类,并且可以像java中的其他任何类一样具有多个实例。
AvrDragon 2014年

35
是的,这太可惜了,构造函数应该是私有的,因此可以确保它是一个双闪的……
fortran

15
@fortran +1表示“ twingleton”。
Bennett McElwee

1
在这个习语上使用Apache BooleanUtils绝对没有意义。
StaxMan '19

82

使用Apache BooleanUtils

(如果峰值性能是您项目中最重要的优先事项,请查看不需要包含外部库的本机解决方案的其他答案之一。)

不要重新发明轮子。利用已经构建和使用的东西isTrue()

BooleanUtils.isTrue( bool );

检查Boolean值是否为true,并null通过返回进行处理false

如果您不仅仅局限于“允许”包含的库,那么对于各种用例,都有很多很棒的帮助器函数,包括 Booleans和)Strings。我建议您仔细阅读各种Apache库,看看它们已经提供了什么。


59
当替代方案使用外部库来实现这种基本功能时,重塑轮子似乎并不那么糟糕。
保罗·曼塔

3
@PaulManta我同意这是否是您在Apache Utils库中唯一使用过的东西,但是建议的想法是“细读”这些库以使自己了解其他有用的功能。
约书亚·品特

1
使用这些库会降低性能。因此,对于这种语言的基本内容,您不应使用库。
ACV

6
那个图书馆正在重新发明轮子。我试图尽可能避免使用此类库。
mschonaker

3
@mschonaker如果Apache BooleanUtils重新发明了轮子,那么原来的轮子是什么?这样做的目的是避免创建一堆辅助函数,以模仿诸如此类的库中已经完成的工作。我还在toStringYesNo所有应用程序中都使用了该库。
约书亚·品特

13

Boolean类型可以null。您需要将其null设置为进行检查null

if (bool != null && bool)
{
  //DoSomething
}                   

3
这个答案有什么问题?抛出异常的不是检查布尔值。不必要的降票。
dodexahedron 2012年

2
我同意这是一个完全合理的答案。您可以摆脱异常处理。
Marvo 2012年

14
异常处理是不必要的,此外,异常处理对初学者来说是一个不好的例子。这值得IMO的反对。(是的……我知道它来自示例代码,但是在“答案”中重复此代码似乎可以认可它。)
Stephen C

1
那么正确的方法是什么?我在这里看不到你的答案。
Marvo 2012年

5
正确的方法是上述方法。没有异常处理。另外,异常处理太笼统了,不建议使用。
vellvisher 2012年

8

借助Java 8 Optional的强大功能,您还可以执行以下操作:

Optional.ofNullable(boolValue).orElse(false)

:)


5

布尔值是原始布尔值的对象包装器类。与任何类一样,此类实际上可以为null。出于性能和内存方面的原因,始终最好使用原语。

Java API中的包装器类有两个主要用途:

  1. 提供一种在对象中“包装”原始值的机制,以便可以将原始值包含在为对象保留的活动中,例如将其添加到Collection中,或从具有对象返回值的方法中返回。
  2. 为基元提供各种实用程序功能。这些功能中的大多数与各种转换有关:将原语与String对象进行相互转换,以及将原语和String对象与不同的基数(或基数)进行转换,例如二进制,八进制和十六进制。

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


0

由于您的变量bool指向null,因此您始终会收到NullPointerException,您需要首先使用非null值初始化该变量,然后再对其进行修改。


1
如果仅仅是那样,该catch块将处理NullPointerException。这里的问题是OP尝试将空引用拆箱到原语中。
Mike Adler 2012年

“您将永远” -除示例外,并非总是如此,简化的代码在将变量初始化为null并对其进行测试之间没有任何作用。大概真正的代码不是那么简单,否则整个if测试都可以删除。
nnnnnn'8
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.