in

Java中理解位运算符,附带示例

了解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运算符将对每对相应的位执行and操作:
//    00001010   (num1)
//  & 00000110   (num2)
//  __________
//    00000010   (result)

你可能会使用按位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;
// 按位or运算符将对每对相应的位执行or操作:
//    00001010   (num1)
//  | 00000110   (num2)
//  __________
//    00001110   (result)

按位或运算符的一个用途是组合权限。在操作系统中,文件或进程通常会具有定义某些用户或组允许做什么的权限。

由于一个人可以有权限也可以没有权限,每一个权限可以用一个位来表示。因此,按位或运算符可以用来将权限轻松地组合为一个单独的数字,以便稍后解析它。注意,在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;
// 异或运算符将对每一对对应的位执行异或运算:
// 00001010 (num1)
// ^ 00000110 (num2)
// __________
// 00001100 (result)

异或具有一个有趣的属性:当你对两个数进行异或运算,假设为a和b,你可以对结果再次进行异或运算得到b,反之亦然。换句话说,异或是可逆的。这可以利用来轻松交换两个数而不创建额外的变量。使用该属性,交换两个数可能如下所示:

int a = 5;
int b = 3;

// 交换a和b的值
a = a ^ b;
b = a ^ b;
a = a ^ b;

演示使用按位异或运算符 (^) 切换二进制开关的java类的示例。

©jingzhengli.com

按位补运算符 (~)

使用按位补运算符时,将翻转数字中的每一位,即0变为1,1变为0。在这个演示中,我们显示了全部32位,因为它们都对整数的值有贡献。以下是一个例子:

int num = 42; // 二进制:00000000000000000000000000101010

int result = ~num;
// 按位补运算符将翻转数字的每一位:
// 00000000000000000000000000101010 (num)// ~
// ___________________________________
// 11111111111111111111111111010101 (result)

左移运算符 (<<)

左移运算符,正如你可能猜到的,将一个数字中的所有位向左移动给定的位数。由于我们在二进制中工作,对于每次左移,我们实际上是将该数乘以2。以下是一个例子。

int num = 5;       // 二进制:00000101

int result = num << 2;
// 左移操作符将数字的位向左移动指定的位置数:
//    00000101   (num)
//  << 2
//  __________
//    00010100   (result)

请记住,java中的整数始终是32位的。这意味着如果你想在一个较大的整数中存储多个较小的数字,可以这样做。例如:

int x = 3;   // 二进制:00000011
int y = 5;   // 二进制:00000101

// 将x和y打包到一个变量中
int packed = (x << 8) | y;  // 结果:771 (二进制:0000001100000101)

然后,要获取y,我们可以将整数与二进制值11111111 (有时称为“掩码”)进行按位与操作。

int retrievedy = packed & 0b11111111;

继续阅读以了解如何取回x。

右移操作符 (>>)

与左移操作符类似,右移操作符将数字的所有位向右移动指定的位置数。再次注意,由于我们是使用二进制,每次向右移动一位,我们都在将数字减半。

应用右移操作符时,左侧的空位将用符号位(第一位)填充,这也是为什么它被称为有符号右移操作符的原因。这是一个例子:

int num = -42;      // 二进制:11111111111111111111111111010110

int result = num >> 2;
// 右移操作符将数字的位向右移动指定的位置数,填充符号位:
//    11111111111111111111111111010110   (num)
//  >> 2
//  __________
//    11111111111111111111111111110101   (result)

在我们使用左移操作符的示例中,我们将两个数字x和y打包到一个整数中。我们知道如何使用掩码取回y,但是我们也可以使用右移操作符轻松取回x:

int retrievedx = packed >> 8;

无符号右移操作符 (>>>)

无符号右移操作符与普通右移操作符完全相同,只是在左侧的空位上始终填充0。这意味着当你在一个数字上使用无符号右移操作符时,它将始终为正数。下面是一个例子:

int num = -42;      // 二进制:11111111111111111111111111010110

int result = num >>> 2;
// 无符号右移操作符将数字的位向右移动指定的位置数,填充0:
//    11111111111111111111111111010110   (num)
//  >> 2
//  __________
//    00111111111111111111111111110101   (result)

逻辑运算符 vs. 位运算符

在编程中,你可能遇到过这样的代码:

if ([expression1] && [expression2]) {
    dosomething();
}

或者

将下面的内容翻译成中文,保留,,及html标签

if ([expression1] || [expression2]) {
    dosomething();
}

在编程中,这些被称为逻辑运算符。与位运算符相反,逻辑运算符是用来操作布尔值或者求值为布尔值的表达式的。也就是说,原理是一样的。一个为真的语句可以看作是1,假的语句可以看作是0。

当使用逻辑或(||)时,其中一个或者两个表达式必须为真,条件才会通过。对于逻辑与(&&),两个表达式都必须为真,条件才会通过。虽然它们在使用方式上有所不同,但逻辑运算符和位运算符在基本层面上非常相似。

总结

正确使用位运算符可以节省时间,并且使代码更加清晰。虽然我们只使用了整数,但位运算符可以应用于java中的任何基本类型,并且可以以许多巧妙的方式利用它们。

无论您是编写低级代码还是使用位操作技巧,位运算符都是非常有用的工具。现在,让我们回答一些常见问题。

本文顶部的图片来自©wright studio/shutterstock.com。

Written by