如何比较布尔值?

36

以这个为例(摘自Java正则表达式检查器无法工作):

while(!checker) {
    matcher = pattern.matcher(number);
    if(matcher.find())
        checker = true;
    else
        year++;
}

如果使用.equals(false)来检查Boolean checker的值,这会有影响吗?

我知道有这个问题,它非常相似。但是,显然该问题涉及原始类型boolean而不是对象封装类Boolean;因此,.equals()不能应用。

此外,Boolean是否应该与boolean不同处理?


3
为什么你要在这里使用Boolean而不是boolean - Jon Skeet
是的,我不明白这个的用例。看起来像一个纯理论的问题。 - asteri
@JonSkeet 这个问题适用于所有Java布尔比较,而不仅仅是链接中的内容。我想知道所有Boolean比较的最佳实践。 - ylun.ca
2
没有比较Boolean而不是boolean的最佳实践,因为比较对象包装器已经是一种糟糕的实践。哈哈。没有理由使用它,它只会让你面临不必要的错误,比如NullPointerException - asteri
7个回答

79

试试这个:

if (Boolean.TRUE.equals(yourValue)) { 
    // ...
}

作为额外的好处,此比较是空值安全的。

运行无误 - Gaurav

25
根据您的评论,似乎您正在寻找关于使用Boolean包装类的“最佳实践”。但实际上并没有什么最佳实践,因为使用这个类本身就是一个坏主意。唯一需要使用对象包装器的情况是在绝对必须使用时(例如使用泛型Generics,即在类似于HashMap<String, Boolean>中存储boolean等情况下)。使用对象包装器没有任何优势,但有很多缺点,尤其是会导致NullPointerException

如果使用'!'代替.equals()来比较Boolean类型的值,是否有影响?

两种技术都容易受到“ NullPointerException”的影响, 因此在这方面没有区别。在第一种情况下,Boolean将会被拆箱为其相应的boolean值并像正常比较一样进行比较。在第二种情况下,你正在调用Boolean类中的一个方法,它是以下内容:
public boolean equals(Object obj) {
    if (obj instanceof Boolean) {
        return value == ((Boolean)obj).booleanValue();
    }
    return false;
}

无论哪种方式,结果都是相同的。

如果使用.equals(false)来检查布尔值检查器的值,会有影响吗?

如上所述,不会有影响。

次要问题:Boolean应该与boolean有所不同处理吗?

如果您一定要使用Boolean类,则在执行任何比较之前始终检查null。例如:
Map<String, Boolean> map = new HashMap<String, Boolean>();
//...stuff to populate the Map
Boolean value = map.get("someKey");
if(value != null && value) {
    //do stuff
}

这将有效,因为Java会短路条件评估。您也可以使用三元运算符。
boolean easyToUseValue = value != null ? value : false;

但是,说真的...除非你被迫不得不这样做,否则只需使用原始类型即可。


谢谢。关于您对“使用.equals(false)检查布尔检查器的值是否重要”的回答。Sunil和Migol都说.equals()会影响性能。然而,我在这里找到了Steve Kuo的评论链接,似乎与他们的说法相矛盾。谁是正确的?FYI Steve说equals will most likely be inlined by the JIT, so performance isn't an issue - ylun.ca
1
@ylun 两种方法的性能开销不同。第一种需要将 Boolean 拆箱为 boolean,而第二种需要将 false 装箱为 Boolean,然后在 .equals() 方法中从 Object 强制转换回 Boolean。我猜测 .equals() 方法会更慢,但我必须进行实际基准测试来验证。您可以通过执行每个操作数百万次并测量经过的时间来自行测试。 - asteri

2
只要checker不是null,你可以使用!checker,这是在Java 5中可能的,因为这个Boolean变量将自动装箱为原始的boolean值。

2

使用直接条件(如==、!=、!condition)与.equals(condition)相比,将略微提高性能,因为在一个情况下你是从一个对象调用方法,而直接比较则直接执行。


“比较是直接执行”的意思是什么?我的理解是:不需要访问另一个类中的方法来执行比较,因此速度更快? - ylun.ca
是的,基本上是因为您正在链接到超类并从中调用方法。但是根据比较的性质,您可能希望坚持使用.equals()而不是'=='。 - ucsunil
好的,我已经对你和@Migol所说的进行了一些研究。我发现了这个。更具体地说,Steve Kuoequals将很可能被JIT内联,因此性能不是问题。他的意思是什么? - ylun.ca
糟糕,错过了编辑时间限制。关于我上面的评论,史蒂夫的评论似乎与您关于性能的陈述相矛盾。 - ylun.ca

2

关于直接操作和方法.equals()的性能。 .equals()方法似乎比==大约慢4倍

我运行了以下测试..

对于==的性能:

public class BooleanPerfCheck {

    public static void main(String[] args) {
        long frameStart;
        long elapsedTime;

        boolean heyderr = false;

        frameStart = System.currentTimeMillis();

        for (int i = 0; i < 999999999; i++) {
            if (heyderr == false) {
            }
        }

        elapsedTime = System.currentTimeMillis() - frameStart;
        System.out.println(elapsedTime);
    }
}

对于.equals()的性能表现:

public class BooleanPerfCheck {

    public static void main(String[] args) {
        long frameStart;
        long elapsedTime;

        Boolean heyderr = false;

        frameStart = System.currentTimeMillis();

        for (int i = 0; i < 999999999; i++) {
            if (heyderr.equals(false)) {
            }
        }

        elapsedTime = System.currentTimeMillis() - frameStart;
        System.out.println(elapsedTime);
    }
}

== 的总系统时间为 1

.equals() 的总系统时间在 3 - 5 之间变化

因此,可以肯定地说,.equals() 会影响性能,并且在大多数情况下使用 == 来比较 Boolean 更好。


1
很好的回答。如果其中任何一个为空,使用“==”会有问题吗? - Sebastian D'Agostino

1

.equals(false) 会比较慢,因为你是在调用对象上的虚拟方法,而不是使用更快的语法。大多数程序员都不太预料到这种情况,因为通常使用的代码标准并不假定你应该通过 .equals(false) 方法进行检查。


除了系统性能外,这两种方式没有任何区别吗? - ylun.ca
@ylun,嗯,你也有编码规范 - 使用该方法会违反它们。 - Migol
有没有关于比较约定的具体文档?我在Oracle的Java约定中找不到它们。 - ylun.ca
1
@ylun 这是众所周知的惯例,而且在我十年的编程经验中,我从未见过任何人在他们的代码中使用.equals(false)作为标准。阅读其他人的代码,查看Java文档中的示例 - 你不会找到它。 - Migol

0

作为对象?

equals

public boolean equals(Object obj)

如果参数不为 null 并且是表示与此对象相同布尔值的 Boolean 对象,则返回 true。

覆盖: Object 类中的 equals

参数: obj - 要比较的对象。

返回: 如果 Boolean 对象表示相同的值,则返回 true;否则返回 false。

boolean a = true;
boolean b = false;

System.out.println("a.equals(b):" + ((Object)a).equals( ((Object)b) ));

输出:a.equals(b):false


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接