ChatGPT解决这个技术问题 Extra ChatGPT

检查 null Boolean 是否为真导致异常

我有以下代码:

Boolean bool = null;

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

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

上面关于对象拆箱的答案都是正确的。但是,为了完整起见,您也可以更改代码以使用原始“布尔”而不是对象包装器“布尔”。您还应该重新了解基元和对象之间的区别。
同时... if (bool == Boolean.TRUE) 评估为 false 而不产生异常。在我刚刚发现的情况下,不确定这是否是故意的。
@simon.watts 对于 boolnull 或者如果 Boolean 是明确构造的(而不是作为对 Boolean.TRUE 的引用),这将是错误的。所以不推荐;而 if (Boolean.TRUE.equals(bool)) 将按预期工作,包括安全处理 null 值。

S
Steven Byle

如果您不喜欢额外的空检查:

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

@AvrDragon:是否需要等于?运算符 == 在这里有效,因为 Boolean 只有两个值
@Atul是的,这里需要equals。因为 (new Boolean(true) == new Boolean(true)) 是.... 假的。原因:布尔只是一个类,可以像java中的任何其他类一样有多个实例。
是的,真可惜,构造函数应该是私有的,所以它确保它是一个 twingleton...
这正是 Apache BooleanUtils 的 BooleanUtils.isTrue( bool ); 所做的。
在这个习语上使用 Apache BooleanUtils 绝对没有意义。
K
K-ballo

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

在您的特定情况下,您的 Booleannull,并且 if 语句触发到 boolean 的隐式转换,从而产生 NullPointerException。您可能需要:

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

从技术上讲,Boolean 可以是任意数量的真实实例,而不仅仅是 Boolean.TRUE。例如 new Boolean(true)
我很难理解为什么 if (myBoolean)(其中 myBooleanBoolean)不会引发编译器错误或至少是警告。这肯定是一个问题。
@JoshM。这是因为 Java 对包装器进行 BoxingUnboxingdocs.oracle.com/javase/tutorial/java/data/autoboxing.html
@Vinicius 当然,但是在这种情况下,编译器应该为我们做空,至少通过编译器警告。
J
Joshua Pinter

使用 Apache BooleanUtils

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

不要重新发明轮子。利用已构建的内容并使用 isTrue()

BooleanUtils.isTrue( bool );

检查 Boolean 值是否为真,通过返回 false 处理 null

如果您不限于“允许”包含的库,还有许多适用于各种用例的强大辅助函数,包括 BooleansStrings。我建议您仔细阅读各种 Apache 库,看看它们已经提供了什么。


当替代方案是使用外部库来做这样基本的事情时,重新发明轮子似乎并没有那么糟糕。
@PaulManta 如果这是您在 Apache Utils 库中唯一使用过的东西,我同意,但建议的想法是“细读”这些库,让您自己接触其他有用的功能。
那个图书馆正在重新发明轮子。我尽量避免使用这样的库。
@mschonaker 如果 Apache BooleanUtils 正在重新发明轮子,那么 original 轮子是什么?这样做的目的是避免创建一堆模仿此类库中已经完成的功能的辅助函数。我还在我的所有应用程序中使用此库中的 toStringYesNo
原来的轮子不是Boolean.TRUE.equals(bool)吗? BooleanUtils 中肯定有一些有用的方法,但您不需要它。
p
provisota

或者借助 Java 8 Optional 的强大功能,您也可以这样做:

Optional.ofNullable(boolValue).orElse(false)

:)


这个答案应该得到更多的认可,但这只是我的看法。
d
dimo414

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

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

O
Orlan

Boolean 是原始布尔值的对象包装类。这个类,与任何类一样,确实可以为空。出于性能和内存原因,最好始终使用原语。

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

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

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


R
RicardoE

由于您的变量 bool 指向空值,因此您将始终得到 NullPointerException,您需要先在某个地方使用非空值初始化变量,然后再对其进行修改。


如果只是这样,catch 块将处理 NullPointerException。这里的问题是 OP 试图将空引用拆箱成原语。
“你将永远” - 并非总是如此,除了示例,简化的代码在将变量初始化为 null 和测试它之间不做任何事情。据推测,真正的代码不会那么简单,否则整个 if 测试可能会被删除。
b
bjmi

if (bool) 将编译为 if (bool.booleanValue()),如果 boolnull,则会抛出 NPE

可空盒装布尔评估的其他解决方案:

JDK 9+ 导入静态 java.util.Objects.requireNonNullElse; if (requireNonNullElse(bool, false)) { // DoSomething

Google Guava 18+ 导入静态 com.google.common.base.MoreObjects.firstNonNull; if (firstNonNull(bool, false)) { // DoSomething

false 用于此处的 null 情况。


O
Ole V.V.

对象.equals()

K-ballo 接受的答案没有任何问题。如果您喜欢一个简单的条件并且像我一样不喜欢 Yoda 条件,那么从 java 1.7 开始,答案是

    if (Objects.equals(bool, true)) {

或者如果同时你更喜欢非常明确

    if (Objects.equals(bool, Boolean.TRUE)) {

或者更好:避免这个问题

不建议使用 Boolean 对象,因此首先允许 Boolean 引用为 null。像您看到的那样的 NullPointerException 的风险太大了。如果您需要一种三态逻辑,最好定义一个具有三个值的枚举。例如

enum MyTristateBoolean { FALSE, DONT_KNOW, TRUE }

现在我们根本不需要 null。中间常量可能应该命名为 UNKNOWNUNDEFINEDNOT_EXISTING 或其他名称,具体取决于您的具体情况。如果合适,您甚至可以将其命名为 NULL。现在根据口味,您的比较成为以下两者之一。

    if (myBool.equals(MyTristateBoolean.TRUE)) {

    if (myBool == MyTristateBoolean.TRUE) {

后者有效,因为编译器保证每个枚举常量只有一个实例。正如大多数人所知,== 不适用于比较非枚举类型的对象是否相等。