什么时候应该使用布尔值的空值?

Javaboolean允许值为 truefalse,而 Boolean 允许值为 truefalsenull。我已经开始将我的 boolean转换成 Boolean。这可能导致以下测试中的崩溃

Boolean set = null;
...
if (set) ...

而测试

if (set != null && set) ...

似乎有点做作,容易出错。

如果有的话,什么时候使用带空值的 Boolean是有用的?如果从来没有,那么包装对象的主要优点是什么?

更新: 有如此多的有价值的答案,以至于我在自己的答案中总结了其中的一些。我充其量只是 Java 的中级水平,所以我试着展示一些我觉得有用的东西。请注意,这个问题是“措辞不正确”(布尔值不能“有一个空值”) ,但我留下了它,以防其他人有同样的误解

150285 次浏览

有三个快速的原因:

  • 来表示数据库的布尔值,这些值可以是 truefalsenull
  • 表示用 xsd:nillable="true"声明的 XML 架构的 xsd:boolean
  • 能够使用泛型类型: List<Boolean>-你不能使用 List<boolean>

原语的包装类可以用在需要对象的地方,集合就是一个很好的例子。

想象一下,由于某种原因,您需要在 ArrayList中存储一个 boolean序列,这可以通过在 Boolean中装箱 boolean来完成。

关于这个 给你有几句话

来自文档:

任何 Java 程序员都知道,不能放入 int (或其他原语) 集合只能保存对象引用, 因此必须将基元值装箱到适当的包装类中 (在 int 的情况下是 Integer) 集合,就会得到输入的 Integer; 如果需要 你必须使用 intValue 方法解除 Integer 的盒子 装箱和取消装箱是一个痛苦的过程,并且会使您的代码变得混乱 自动装箱和取消装箱功能使过程自动化,从而消除 痛苦和混乱。

Http://docs.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html

我认为在某些情况下,您应该有一种机制来区分已经设置值或未设置值的布尔字段。

我几乎从不使用 Boolean,因为它的语义模糊不清。基本上,您有3个状态逻辑: 真、假或未知。有时使用它是有用的,例如,当你给用户两个值之间的选择,用户没有回答,你真的想知道的信息(认为: NULLable 数据库列)。

我认为没有理由将 boolean转换为 Boolean,因为它会带来额外的内存开销、 NPE 的可能性和更少的输入。通常我使用笨拙的 BooleanUtils.isTrue()来使我的生活更容易一点与 Boolean

Boolean存在的唯一原因是能够拥有 Boolean类型的集合(泛型不允许 boolean以及所有其他原语)。

当您想知道是否分配了与 truefalse不同的值时,Boolean包装器非常有用。它有以下三个州:

  • 没错
  • 假的
  • 没有定义哪个是 null

boolean只有两种状态:

  • 没错
  • 假的

上述差异将使它在 Boolean值的列表中很有帮助,这些值可以是 TrueFalseNull

每次都使用 boolean而不是 Boolean,这样可以避免许多 NullPointerException,使代码更加健壮。

例如,Boolean就很有用

  • 将布尔值存储在集合中(List、 Map 等)
  • 表示可为空的布尔值(例如,来自数据库中的可为空的布尔值列)。在这个上下文中,null 值可能意味着“我们不知道它是真还是假”。
  • 每当一个方法需要一个 Object 作为参数时,你需要传递一个布尔值。例如,当使用反射或者像 MessageFormat.format()这样的方法时。

布尔值的主要用途是空值。以 值表示,该属性未定义为例,数据库中的列可以为空。

如果您真的需要将所有的代码从原始布尔值转换为包装布尔值,那么您可以使用以下代码来支持旧代码:

Boolean set = Boolean.FALSE; //set to default value primitive value (false)
...
if (set) ...

最好的方法是完全避免布尔值,因为每个布尔值都意味着在代码中的任何其他地方都有一个 If判断语句(参见 http://www.antiifcampaign.com/和这个问题: 你能编写任何没有 if 语句的算法吗?)。

然而,实际上您必须不时地使用布尔值,但是,正如您自己已经发现的那样,处理布尔值更容易出错,也更麻烦。所以我建议尽可能使用布尔型。这里的例外情况可能是遗留数据库具有可为空的布尔列,尽管我也会尝试在映射中隐藏这一点。

哇,到底怎么回事? 只有我这么觉得吗? 还是这些答案都是错的,或者至少是误导性的?

布尔类是布尔原语类型的包装器。此包装器的用途是能够在接受对象或泛型的方法中传递布尔值。向量。

布尔对象的值永远不能为 null。如果您的 < em > 参考 到布尔值为 null,这只是意味着您的布尔值从未被创建。

您可能会发现这很有用: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Boolean.java

空布尔引用只能用于触发与其他空引用类似的逻辑。将它用于三个状态逻辑是笨拙的。

编辑: 注意,Boolean a = true;是一个误导性的声明。它实际上等同于 Boolean a = new Boolean(true); 请点击这里查看“自动装箱”http://en.wikipedia.org/wiki/boxing_%28computer_science%29#autoboxing

也许这就是大部分困惑的来源。

编辑2: 请阅读下面的评论。 如果有人知道如何重新组织我的答案,以纳入这一点,请这样做。

回答自己的问题: 我认为回答我自己的问题会很有用,因为我从答案中学到了很多。这个答案是为了帮助那些像我一样对这些问题没有完全理解的人。如果我使用不正确的语言请纠正我。

  • Null“ value”不是一个值,它与 truefalse有根本的不同。缺少指向对象的指针。因此,认为布尔值为3是根本错误的
  • Boolean 的语法是缩写的,并且隐藏了引用指向 Object 的事实:

    Boolean a = true;

隐藏了 true是一个对象的事实。其他等价的赋值可能是:

Boolean a = Boolean.TRUE;

或者

Boolean a = new Boolean(true);
  • 缩写语法

    if (a) ...

与大多数其他赋值不同,并且隐藏了 a 可能是对象引用或基元的事实。如果一个对象是必要的 null测试,以避免 NPE。对我来说,如果有一个平等测试,我在心理上更容易记住这一点:

if (a == true) ...

在这里,我们可能会被提示测试 null。因此,只有当 a是原语时,缩写形式才是安全的。

对于我自己,我现在有一些建议:

  • 对于3值逻辑,永远不要使用 null。只能使用 true 和 false。
  • 不要从方法返回 Boolean,因为它可能是 null。只返回 boolean
  • 仅使用 Boolean来包装容器中的元素或需要对象的方法的参数

布尔包装器中的 * * null * * 值有许多用途! :)

例如,您可能在表单中有一个名为“新闻稿”的字段,该字段指示用户是否希望从您的站点获得新闻稿。如果用户没有在该字段中选择一个值,您可能希望实现该情况下的默认行为(发送?不发?再问一次?等)。显然,没有设置(或者没有选择或者 * * null * *) ,并不等于真或假。

但是,如果“ not set”不适用于您的模型,则不要更改布尔原语;)

在布尔元素的严格定义中,只有两个值。在一个完美的世界里,这是真的。在现实世界中,元素可能丢失或未知。通常,这涉及用户输入。在基于屏幕的系统中,它可以通过编辑来强制执行。在使用数据库或 XML 输入的批处理环境中,元素很容易丢失。

因此,在我们生活的非完美世界中,布尔对象的伟大之处在于它可以将缺失或未知的状态表示为 null。毕竟,计算机只是对现实世界建模,应该考虑到所有可能的状态,并用抛出异常来处理它们(主要是因为在有些用例中,抛出异常才是正确的响应)。

在我的例子中,Boolean 对象是完美的答案,因为输入 XML 有时缺少元素,我仍然可以得到一个值,将它赋给 Boolean,然后在尝试对它进行真或假测试之前检查 null。

只有我的两分钱。

对于上述所有好的答案,我将在 JavaservletHttpSession类中给出一个具体的例子。希望这个例子有助于澄清您可能还有的一些问题。

如果需要存储和检索会话的值,则使用 setAttribute(String,Object)和 getAttribute(String,Object)方法。因此,对于一个布尔值,如果要将其存储在 http 会话中,就必须使用布尔类。

HttpSession sess = request.getSession(false);
Boolean isAdmin = (Boolean) sess.getAttribute("admin");
if (! isAdmin) ...

如果没有设置属性值,最后一行将导致 NullPointerException。(这就是我写这篇文章的原因)。因此,无论你是否喜欢使用它,3个逻辑状态都会保留下来。

当您需要三个状态时,布尔值非常有用。就像在软件测试中,如果测试通过,发送为真,如果测试失败,发送为假,如果测试用例中断,发送为空,这将表示测试用例没有执行。