使用 xor 运算符进行布尔检查是否是一种好的做法?

我个人很喜欢 独家或^操作符,因为它的简洁性使它在布尔检查的上下文中有意义。我更喜欢写作

if (boolean1 ^ boolean2)
{
//do it
}

if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
//do it
}

但是我经常从其他经验丰富的 Java 开发人员(不仅仅是新手)那里得到困惑的表情,有时还有人评论说它应该只用于位操作。

我很好奇关于使用 ^操作符的最佳实践。

142633 次浏览

您可以简单地使用 !=代替。

我想你可以注释一下,比如 // ^ == XOR

如果使用模式证明了它的合理性,为什么不呢?虽然你的团队不能马上认出操作员,但随着时间的推移,他们可以。人类一直在学习新单词。为什么不在编程方面?

我可以说的唯一注意事项是“ ^”不具有第二个布尔检查的短路语义。如果您确实需要短路语义,那么静态 util 方法也可以工作。

public static boolean xor(boolean a, boolean b) {
return (a && !b) || (b && !a);
}

我想你已经回答了你自己的问题——如果你从别人那里得到了奇怪的眼神,那么选择更直白的方式可能更安全。

如果你需要评论它,那么你最好用更详细的版本代替它,而不是让人们在第一时间问这个问题。

我发现我有很多类似的对话。一方面,你有一个紧凑,有效的方法来实现你的目标。另一方面,您有一些其他团队成员可能无法理解的东西,这使得将来很难维护。

我的一般原则是询问所使用的技术是否是一般程序员应该知道的东西。在这种情况下,我认为期望程序员知道如何使用布尔运算符是合理的,因此在 if 语句中使用 xor 是可以的。

举例来说,使用 xor 来交换两个变量,而不使用临时变量,这种做法是不可取的。这是一个我不希望每个人都熟悉的技巧,所以它不会通过代码审查。

可以比较两个变量,但是不能进行多重比较。

if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
//do it
}

恕我直言,这一准则可以简化:

if(boolean1 != boolean2)
{
//do it
}
str.contains("!=") ^ str.startsWith("not(")

对我来说更好看

str.contains("!=") != str.startsWith("not(")

作为一个按位运算符,xor 比其他任何替换它的方法都要快得多。因此,对于性能关键且可伸缩的计算,xor 势在必行。

我个人的主观意见是: 绝对禁止为任何目的使用平等(= = 或!)!=)布尔值。使用它表明缺乏基本的编程道德和基本原则。任何看过 ^ 的人都应该回到布尔代数的基础知识上来(我很想在这里写“信仰的河流”)。

考虑到代码的清晰性,我认为在布尔检查中使用 XOR 并不是 XOR 按位运算符的典型用法。根据我的经验,Java 中的按位 XOR 是用于实现掩码 flag toggle行为的 一般来说:

flags = flags ^ MASK;

Vipan Singla 的这篇 文章更详细地解释了这种用法。

如果您需要像在示例中那样使用按位异或,请注释为什么要使用它,因为它可能需要即使是按位识字的读者停下来理解您为什么要使用它。

你总是可以把它包装在一个函数中,给它一个冗长的名字:

public static boolean XOR(boolean A, boolean B) {
return A ^ B;
}

但是,在我看来,对于那些不知道 ^ 操作符是用来做什么的人来说,快速地谷歌一下并不难。第一次之后就不难记起来了。因为您要求使用其他用途,所以通常使用 XOR 进行位屏蔽。

你也可以 使用 XOR 交换两个变量中的值,而不使用第三个临时变量

// Swap the values in A and B
A ^= B;
B ^= A;
A ^= B;

这是 与异或交换相关的堆栈溢出问题

我个人更喜欢“ boolean1 ^ boolean2”这个表达式,因为它很简洁。

如果我处于你的情况(在一个团队中工作) ,我会采取折衷方案,将“ boolean 1 ^ boolean 2”逻辑封装在一个具有描述性名称的函数中,比如“ isDifferent (boolean 1,boolean 2)”。

例如,不使用“ boolean 1 ^ boolean 2”,而是像下面这样调用“ isDifferent (boolean 1,boolean 2)”:

if (isDifferent(boolean1, boolean2))
{
//do it
}

你的“ isDifferent (boolean1,boolean2)”函数看起来应该是这样的:

private boolean isDifferent(boolean1, boolean2)
{
return boolean1 ^ boolean2;
}

当然,这个解决方案需要使用一个表面上无关的函数调用,这个函数调用本身受到最佳实践的审查,但是它避免了冗长(和丑陋)的表达式“(boolean1 & & !布尔学2) | | (布尔学2 & & !布尔人1)”!