Java中位运算符如何处理布尔值

3
请考虑以下示例。
int i=11, j=5;
boolean b=true, c=false;
System.out.println(b&c); // --> output=false
System.out.println(i&j); // --> output=1

位运算与操作符在布尔变量上的工作原理是什么?

1
我想指出的是,可以在布尔值上使用 & 和 | 的原因是它们不会短路,而 && 和 || 会短路。 - ILMTitan
4个回答

12
在Java中,布尔类型不支持位运算。但是,逻辑运算(在JLS的§15.22.2中指定)可以使用&|进行操作。
  • &表示逻辑与(仅当两个参数均为true时才返回true
  • |表示逻辑或(当至少一个参数为true时返回true)。
请注意,按位运算也使用相同的运算符,但是只有当两个操作数都可以转换为整数类型(即bytecharshortintlong及其相应的包装器)时才适用。
由于这篇文章引起了一些...激烈的讨论,我想澄清一下我坚持“按位”和“逻辑”操作之间差异的原因。
首先:是的,在某个层面上,这两个操作将完全相同,除了它们的输入大小(由于优化可能甚至是相同的)。

但是,这里至少有3个层次:

  • Java语言

    Java语言规范boolean定义为具有两个值truefalse的原始类型。它没有为这些值定义数字值,也没有直接将其转换为数字类型或反之(请参见§4.2.2的最后一句话)。

  • Java虚拟机

    Java虚拟机规范 定义了boolean类型,但提供了非常少的支持。

    它还对转换进行了如下说明

    Java虚拟机使用1表示true,0表示false来编码boolean数组组件。在编译器将Java编程语言boolean值映射到Java虚拟机类型int值的情况下,编译器必须使用相同的编码方式。

    JVM中实现此要求的最简单方法显然是让1true0是false,并将转换操作作为无操作执行。这也是最可能的实现方式,但不一定是唯一正确的实现方式。

  • 硬件

    这因CPU而异,但大多数CPU都不支持boolean类型(为什么要支持?),因此对boolean的操作在这里将使用正常的位运算。


如果您观察上面的输出,当我们对整数进行位运算时,它表现得非常完美。但是当我们进行布尔位运算时,它会返回true或false... 当JVM在布尔变量上执行位运算时,它实际上在做什么? 它是否将true作为内部数字值处理? - Bhadri
我同意这是布尔逻辑,但它仍被视为位运算。你还忘了提到位移操作。 - Trevor Arjeski
2
Java中的boolean类型没有位运算。就是这么简单。在上面的示例中(a&b)发生的是逻辑与,正如JLS中所指定的那样(请参见我的答案中的链接)。 - Joachim Sauer
@Trevor:但他问的是“布尔值如何处理”(重点在我这里)。 - Joachim Sauer
2
@Trevor:我如此坚持的原因不是因为我的自尊心(谢谢,它很好;-)),而是因为这是与C(和一些基于C的语言)的重要区别:boolean是一种独立的类型,而不仅仅是“非常小的整数”。JLS就是这样处理它的,它可能有一个很好的理由。 - Joachim Sauer
显示剩余9条评论

9

对于布尔类型:

运算符&&&被视为逻辑AND。

运算符|||被视为逻辑OR。

您还可以使用^执行XOR,使用!执行NOT。


这在JVM中如何工作,与位操作整数相比如何?

在字节码级别上,FALSE的值为0,TRUE的值为1。来自javap -c java.lang.Boolean

static {};
  Code:
   0:   new     #56; //class java/lang/Boolean
   3:   dup
   4:   iconst_1
   5:   invokespecial   #89; //Method "<init>":(Z)V
   8:   putstatic       #86; //Field TRUE:Ljava/lang/Boolean;
   11:  new     #56; //class java/lang/Boolean
   14:  dup
   15:  iconst_0
   16:  invokespecial   #89; //Method "<init>":(Z)V
   19:  putstatic       #85; //Field FALSE:Ljava/lang/Boolean;

在这段代码中,它将TRUE定义为new Boolean(true),你可以看到使用iconst_1true推入堆栈,类似于push(1)。同样,iconst_00用于false
如果将false <=> 0true <=> 1进行映射,您会发现&|对于intboolean的工作方式相同。

4

针对你的情况,我认为&&&之间唯一的区别在于,对于&,即使第一个操作数的值为false,第二个操作数仍将被计算,而对于&&,如果第一个操作数的值为false,则不会计算第二个操作数。

如果您的表达式中有昂贵的方法,这一点尤为相关。


0

你所进行的第一个操作 - TRUE & FALSE 被视为 1 和 0,即 false。

第二个操作 - 11 & 5 被视为二进制值 1011 和 0101 进行与运算,结果为 0001。


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