了解java中的位运算符可以在许多情况下非常有用,尤其是在处理低级操作时。有多种位运算符要考虑,但它们都相当简单。
虽然位运算符通常不是必需的,但如果你想对java编程有牢固的掌握,了解它们是很重要的。所以,让我们开始吧!
什么是位运算符?
位运算符允许程序员对数据进行位级操作,从而可以提取或操作特定的位。你可能希望利用这一点的原因有很多,但首先,让我们回顾一下什么是位。
位回顾
如你所知,计算机是通过电信号工作的,而电的存在或不存在通常表示为二进制,也就是二进制。即使大部分细节被抽象掉了,这个原则在java中也适用。
数据被表示为一定数量的位或二进制数位。例如,在java中,一个整数是32位。这通常允许你表示的数字高达2,147,483,647(当一个位被用作符号位时,表示它是正数还是负数。)但是,在本文中,我们将主要使用可以表示为8位的数字。
and运算符(&)
and运算符将对两个数字执行按位and操作。这意味着对于结果数字中的每个位,只有在操作数中的两个位都是1时,它才是1,否则为0。下面是一个例子:
int num1 = 10; // 二进制:00001010 int num2 = 6; // 二进制:00000110 int result = num1 & num2; |
你可能会使用按位and运算符的一个例子是当你尝试找到一个数字的奇偶性(它是偶数还是奇数)时。你可以通过将其与1进行and运算来实现这一点。如果结果为0,则该数字是偶数。
int number = 13; boolean iseven = (number & 1) == 0; // 结果:false |
演示使用按位and运算符来确定一个数字是偶数还是奇数的java类的示例。
©jingzhengli.com
or运算符(|)
or运算符将对两个数字执行按位or操作。当使用时,对于结果数字中的每个位,如果操作数中的任一位为1或者两个位都为1,则它将为1,否则为0。这也被称为包含or操作。下面是一个例子:
int num1 = 10; // 二进制:00001010 int num2 = 6; // 二进制:00000110 int result = num1 | num2; |
按位或运算符的一个用途是组合权限。在操作系统中,文件或进程通常会具有定义某些用户或组允许做什么的权限。
由于一个人可以有权限也可以没有权限,每一个权限可以用一个位来表示。因此,按位或运算符可以用来将权限轻松地组合为一个单独的数字,以便稍后解析它。注意,在java中,可以通过在前面加上0b来表示二进制数。像这样的东西是相当常见的:
int readpermission = 0b00000001; int writepermission = 0b00000010; // 结合读和写权限 int combinedpermissions = readpermission | writepermission; // 结果:0b00000011 |
异或运算符 (^)
异或运算符将对两个数执行按位异或运算。对于结果中的每一位,如果操作数中的任一位为1,则该位将为1,但如果两个位都为1,则该位将为0。由于我们忽略了两个位都为1的情况,所以这被称为异或运算。以下是一个例子:
int num1 = 10; // 二进制:00001010 int num2 = 6; // 二进制:00000110 int result = num1 ^ num2; |
异或具有一个有趣的属性:当你对两个数进行异或运算,假设为a和b,你可以对结果再次进行异或运算得到b,反之亦然。换句话说,异或是可逆的。这可以利用来轻松交换两个数而不创建额外的变量。使用该属性,交换两个数可能如下所示:
int a = 5; int b = 3; // 交换a和b的值 |
演示使用按位异或运算符 (^) 切换二进制开关的java类的示例。
©jingzhengli.com
按位补运算符 (~)
使用按位补运算符时,将翻转数字中的每一位,即0变为1,1变为0。在这个演示中,我们显示了全部32位,因为它们都对整数的值有贡献。以下是一个例子:
int num = 42; // 二进制:00000000000000000000000000101010
int result = ~num; |
左移运算符 (<<)
左移运算符,正如你可能猜到的,将一个数字中的所有位向左移动给定的位数。由于我们在二进制中工作,对于每次左移,我们实际上是将该数乘以2。以下是一个例子。
int num = 5; // 二进制:00000101
int result = num << 2; |
请记住,java中的整数始终是32位的。这意味着如果你想在一个较大的整数中存储多个较小的数字,可以这样做。例如:
int x = 3; // 二进制:00000011 int y = 5; // 二进制:00000101 // 将x和y打包到一个变量中 |
然后,要获取y,我们可以将整数与二进制值11111111 (有时称为“掩码”)进行按位与操作。
int retrievedy = packed & 0b11111111; |
继续阅读以了解如何取回x。
右移操作符 (>>)
与左移操作符类似,右移操作符将数字的所有位向右移动指定的位置数。再次注意,由于我们是使用二进制,每次向右移动一位,我们都在将数字减半。
应用右移操作符时,左侧的空位将用符号位(第一位)填充,这也是为什么它被称为有符号右移操作符的原因。这是一个例子:
int num = -42; // 二进制:11111111111111111111111111010110
int result = num >> 2; |
在我们使用左移操作符的示例中,我们将两个数字x和y打包到一个整数中。我们知道如何使用掩码取回y,但是我们也可以使用右移操作符轻松取回x:
int retrievedx = packed >> 8; |
无符号右移操作符 (>>>)
无符号右移操作符与普通右移操作符完全相同,只是在左侧的空位上始终填充0。这意味着当你在一个数字上使用无符号右移操作符时,它将始终为正数。下面是一个例子:
int num = -42; // 二进制:11111111111111111111111111010110
int result = num >>> 2; |
逻辑运算符 vs. 位运算符
在编程中,你可能遇到过这样的代码:
if ([expression1] && [expression2]) { dosomething(); } |
或者
将下面的内容翻译成中文,保留,,及html标签
if ([expression1] || [expression2]) { dosomething(); } |
在编程中,这些被称为逻辑运算符。与位运算符相反,逻辑运算符是用来操作布尔值或者求值为布尔值的表达式的。也就是说,原理是一样的。一个为真的语句可以看作是1,假的语句可以看作是0。
当使用逻辑或(||)时,其中一个或者两个表达式必须为真,条件才会通过。对于逻辑与(&&),两个表达式都必须为真,条件才会通过。虽然它们在使用方式上有所不同,但逻辑运算符和位运算符在基本层面上非常相似。
总结
正确使用位运算符可以节省时间,并且使代码更加清晰。虽然我们只使用了整数,但位运算符可以应用于java中的任何基本类型,并且可以以许多巧妙的方式利用它们。
无论您是编写低级代码还是使用位操作技巧,位运算符都是非常有用的工具。现在,让我们回答一些常见问题。
本文顶部的图片来自©wright studio/shutterstock.com。