Boolean.TRUE 和 true 有什么区别

What the difference between Boolean.TRUE and true

首先,我有

private Map<String, Boolean> mem = new HashMap<String, Boolean>();

然后:

  if (wordDict.contains(s) ||  Boolean.TRUE==mem.get(s)) {
        return true;
    }

为什么我不能在 if 语句中使用 "mem.get(s)==true"。会出现错误"Line 6: java.lang.NullPointerException"

我想我还是不能很好地理解 wrapper class。请给我一些指导。谢谢!

如果 mem.get(s) 为 null 并将与原始布尔值进行比较,java 将进行自动装箱。这意味着它将调用 null.booleanValue().

这就是你获得 NPE 的原因。

这更像是一个逻辑问题,而不是基于语言的问题。如果 s 不在 mem 中,if(mem.contains(s) || Boolean.TRUE == mem.get(s)) 将只检查条件的第二部分。因此比较等同于 Boolean.TRUE == null。由于 Boolean.TRUE 是一个 Boolean 对象,比较是在两个引用之间进行的(并且总是 return false)。另一方面,boolean 是原始类型,因此必须首先转换从 mem 检索到的 Boolean。由于它是 null,因此无法转换为原始类型。

看起来是 mem.get(s) returns Boolean 类型的结果。在 java 中有两种处理逻辑值的类型。 Boolean 对象类型和 boolean 原始类型。

为了计算 if 语句的逻辑表达式,java 将 Boolean 转换为 boolean using autoboxing

但是如果您的方法 returns null 而不是 Boolean 对象,则 java 无法将此值拆箱为布尔原始类型。然后你得到 NullPointerException。

只要字典不包含 swordDict.contains(s)false),就会计算第二个条件 (mem.get(s) == true)。

在 Java 的地图库中,试图获取不存在的键的值 returns null。因此,每次该键不在 mem 映射中时,都会返回 null,并与 true 进行比较(使用 ==)。当 Boolean 类型与 boolean 值进行比较或赋值时,它是 'autounboxed'。这意味着 Boolean.booleanValue() 方法被调用。如果 Booleannull,这就是导致异常的原因,因为它意味着调用 null.booleanValue()null 什么都不是,所以它不知道如何成为布尔值!

包装器 classes 是有用的构造,它使基本类型能够与继承自 Object 的类型进行互操作,即引用类型(其他所有内容)。当您处理基本类型('value' 类型)时,它们的值直接存在于它们被描述的位置 - 作为用于执行当前函数(对于局部变量)的内存的一部分或作为一部分内存 space 分配给 its 内存 space 中的对象(用于字段变量)。当您处理引用类型(那些继承自 Object,包括 Boolean 和其他包装类型)时,被引用的数据反而存在于称为 [=47= 的内存 space 中].除了这个堆内存分配,为了知道那个对象在哪里,类似于值类型的值的实体实际上是一个对对象内存位置的引用,存储为局部变量或字段变量,不是对象本身的值或数据。这就是使它们成为 null 的原因:null 引用表明该变量没有特别指向任何内容。 (阅读有关堆栈和堆分配的更多详细信息。)

Boolean.TRUE 比较安全的原因是因为在 Object 类型上,例如 Boolean(以及任何原始类型的包装器 classes) , Boolean 类型的变量实际上是一个引用。这意味着 == 运算符实际上正在检查 if the references are the same - 即内存中的实际对象是否相同(具有相同的内存位置),而不是它们是否 'equal' 某个值 -基于 'equal' 的定义。您不希望这样,因为您可能会得到令人惊讶的结果,例如 new Boolean(true) == new Boolean(true) 返回 false。顺便说一句,这就是我们使用 equals 方法的原因 - 这应该由任何 class 定义,用于希望按值而不是按引用进行比较的对象。另一方面,对于原始值类型,如 boolean== 运算符按字面意思比较值。这就是为什么让包装器类型自动装箱和拆箱很有用 - Boolean 变量(不是 'dereferenced' - 找到它指向的值)实际上是一个参考值,指的是内存位置。 boolean 变量是一个实际的布尔值。因此,如果没有自动拆箱和装箱,尝试比较两者是没有意义的。

如果您想确保 mem.get(s) 的值既不是 null,也不是 false,请使用类似 mem.containsKey(s) && mem.get(s) == true 的值。第一次检查确保不会有空引用。