1. 概述

Java在内存中以二进制形式存储数字。理解整数在位级别上的表示方式有助于我们进行某些操作。

在这个教程中,我们将探讨Java中数字表示的一些细节,并了解Java的位操作是如何工作的。

2. Java中的位操作

在Java中,整数使用32位表示,长整型使用64位。需要注意的是,Java采用补码表示法来表示负数。在这种情况下,如果第一个位是1,那么这个数字就被视为负数。负数的计算方法是取数值,将所有1和0翻转,然后加1。

例如,在8位中,数字6的二进制表示是0b00000110。要将其转换为-6,我们需要反转为0b11111001,然后加上1,结果变为0b11111010

此外,位操作为许多用例奠定了基础,因为它们通常比完整的数学或逻辑表达式对CPU来说更快。

2.1. 与运算符 (&)

与运算符(&)执行两个32位整数之间的位与操作:

int result = 0b1100 & 0b0111;
assertEquals(0b0100, result);

这个操作独立地评估每个位的位置。如果两个操作数对应位都是1,结果将在该位置上有一个1;否则,它将是0。在提供的示例中:

  • 12的二进制表示(0b1100)
  • 7的二进制表示(0b0111)
  • 位与操作得到0b0100
  • 结果为十进制值4

2.2. 或运算符 (|)

或运算符(|)对两个数相同位置的位执行位或操作:

int result = 0b1100 | 0b0111;
assertEquals(0b1111, result);

与与运算符类似,或运算符比较每个位位置。如果操作数中相应位至少有一个是1,结果将在该位置有一个1。在这个例子中,结果是0b1111,相当于十进制值15。

2.3. 异或运算符 (^)

我们可以使用异或运算符(^)执行位异或操作,其中对应位相互作用:

int result = 0b1100 ^ 0b0111;
assertEquals(0b1011, result);

这个操作如果操作数中相应位不同,则设置结果位为1。在提供的示例中,结果是0b1011,对应十进制值11。

2.4. 位取反运算 (~)

位取反运算符(~)反转其操作数的位,将1变为0,0变为1:

int result = ~0b0101;
assertEquals(-0b0110, result);

每个位都被反转,将0变为1,反之亦然。结果是\-0b0110,使用补码表示法相当于十进制值\-6

2.5. 左移(*)和右移(>>)

左移(*)运算符将数字的位向左移动指定的位数:

int result = 0b0101 << 2;
assertEquals(0b10100, result);

在这里,我们在变量a中存储的值上执行位左移操作。此外,这个操作将二进制表示向左移动两位,并在右侧填充零。

同样,右移(>>)运算符将位向右移动:

int result = 0b0101 >> 1;
assertEquals(0b10, result);

相反,我们执行位右移操作,将变量a的二进制表示向右移动一位。左侧的空位对于有符号整数会根据符号位填充。所以正数保持正,负数保持负。

3. 实际应用案例:使用位操作修改颜色

在这个实际示例中,我们将探索如何使用位操作来修改RGB值的颜色。

3.1. 原始颜色和掩码

int originalColor = 0xFF336699;
int alphaMask = 0xFF000000;
int redMask = 0x00FF0000;
int greenMask = 0x0000FF00;
int blueMask = 0x000000FF;

这里,我们将原始颜色初始化为0xFF336699,这是RGB颜色的十六进制表示。另外定义了四个掩码(alphaMask、redMask、greenMask和blueMask),根据位位置提取颜色组件。

3.2. 提取颜色成分

int alpha = (originalColor & alphaMask) >>> 24;
int red = (originalColor & redMask) >>> 16;
int green = (originalColor & greenMask) >>> 8;
int blue = originalColor & blueMask;