在今天的课程中,我们将熟悉 Java 的位运算符,并考虑一些如何使用的例子。你可能对“比特”这个词很熟悉。如果不熟悉,我们来回忆一下是什么意思:)
一个位是计算机中最小的信息单位。它的名字来自二进制数字。一个位可以用两个数字中的一个来表示:1 或 0。有一种基于 1 和 0 的特殊二进制数字系统。
我们不会在这里钻研数学。我们只注意到 Java 中的任何数字都可以转换成二进制形式。为此,你需要使用包装类。
例如,你可以这样对一个 int 变量使用包装类:
现在我们把每一位都向左移动 3 个位置:
看看我们得到了什么。如你所见,我们所有的位都已移位,并且从范围的边缘添加了另外 3 个零。三,因为我们移动了 3 位。如果我们移位 10,就会增加 10 个零。
自然,这对应的是十进制中的 0。
记住向左移动有一个简单的规则:
每向左移动一次,数字就乘以 2。
让我们试着在没有比特图的情况下计算下面的表达式
111111111 << 3
我们需要将数字 111111111 乘以 2。结果我们得到 888888888。让我们编写一些代码并进行检查:
![Java 位运算符 - 4]()
由于向右移动了 2 位,我们数字中的两个极远端的零移出了范围并丢失了。我们得到 10000,这相当于十进制中的数字 16
控制台输出:
所有操作都从左到右执行,并考虑其优先级。
例如,如果我们编写此程序:
![Java 位运算符 - 6]()
public class Main {
public static void main(String[] args) {
int x = 342;
System.out.println(Integer.toBinaryString(x));
}
}
控制台输出:
101010110
1010 10110(我加了空格是为了方便阅读)是十进制中的数字 342。我们实际上已经把这个数字分解成了单个的比特:0 和 1。对位执行的操作称为按位操作。- ~ — 按位非。
101010110 是用二进制数表示的 342
010101001 是表达式 ~342 的值
让我们试着将其付诸实施:
public class Main {
public static void main(String[] args) {
int x = 342;
System.out.println(~x);
}
}
控制台输出:
169
169 是我们熟悉的十进制系统中的结果 (010101001) :)- & — 按位与
110110000 是用二进制数表示的 277
1000101011 是用二进制数表示的 432
接下来,运算符 & 将高位数字的第一位与低位数字的第一位进行比较。因为这是一个与运算符,所以只有两位都为 1 时,结果才会为 1。在任何其他情况下,结果为 0。
100010101
&
110110000
_______________
10001000 — & 运算符的结果
首先,我们比较两个数组的第一位、第二位、第三位,依此类推。
正如你所看到的,只有在两种情况下,数字中对应的两个位都等于 1(第一位和第五位)。所有其他比较都产生 0。
所以最后我们得到了数字 10001000。在十进制系统中,它对应于数字 272。我们检查下:
public class Main {
public static void main(String[] args) {
System.out.println(277&432);
}
}
控制台输出:
272
- | — 按位或。
public class Main {
public static void main(String[] args) {
System.out.println(277|432);
}
}
控制台输出:
437
我们计算的一切都是正确的!:)- ^ — 按位异或
public class Main {
public static void main(String[] args) {
System.out.println(277^432);
}
}
控制台输出:
165
超赞!一切正如我们所料 :)
现在该熟悉位移运算符了。
该运算符名字本身就不言自明。我们取一个数,将其位向左或向右移动 :)让我们看看变成什么样子:
左移
比特向左移位由 << 指示 下面是一个示例:
public class Main {
public static void main(String[] args) {
int x = 64;//值
int y = 3;// 移动距离
int z = (x << y);
System.out.println(Integer.toBinaryString(x));
System.out.println(Integer.toBinaryString(z));
}
}
在这个例子中,数字 x = 64 称为值。我们要移动的是值的一部分。我们将把这些位向左移(你可以通过 << 操作符的方向猜到这一点)
在二进制系统中,数字 64 = 1000000
数字 y = 3 称为移动距离。移位距离表示你想要将数字 x 的位向右/向左移位多少位
在例子中,我们将将数字左移 3 位。
为了更清楚地看到移位过程,请参见图片。
在此例子中,我们使用 int。int 在计算机内存中占 32 位。这是最初的数字 64 的样子:


因此,表达式 x << y 表示“将数字 x 的位向左移动 y 位”。表达式的结果是数字 1000000000,在十进制中是 512。 我们检查下:
public class Main {
public static void main(String[] args) {
int x = 64;//值
int y = 3;// 移动距离
int z = (x << y);
System.out.println(z);
}
}
控制台输出:
512
完全正确!
理论上,这些位可以无限移位,但是因为我们的数字是 int,所以我们只有 32 个二进制数字可用。其中,7 个已经被 64 (1000000) 占用。
因此,如果我们向左移动 27 个位置,我们唯一的一个位置将超出数据类型的范围而丢失。
只有零会留下!
public class Main {
public static void main(String[] args) {
int x = 64;//值
int y = 26;// 移动距离
int z = (x << y);
System.out.println(z);
}
}
控制台输出:
0
不出所料,1 移到 32 个可用位之外并消失了。我们以一个仅由零组成的 32 位数字结束。

public class Main {
public static void main(String[] args) {
System.out.println(111111111 << 3);
}
}
888888888
右移
该操作由 >> 表示。 该操作功能相同,但方向不同!:) 我们不会重新发明轮子。我们使用同一个 int 64 试试。
public class Main {
public static void main(String[] args) {
int x = 64;//值
int y = 2;// 移动距离
int z = (x >> y);
System.out.println(z);
}
}


16
记住向右移动有一个简单的规则:
每次向右移位除以 2,丢弃任何余数。
例如:
35 >> 2
意味着我们需要将 35 除以 2 两次,去掉余数
35/2 = 17(去掉余数 1)
17/2 = 8(去掉余数 1)
最终,35 >> 2 应该等于 8。
我们检查下:
public class Main {
public static void main(String[] args) {
System.out.println(35 >> 2);
}
}
控制台输出:
8
Java 中的运算符优先级
在编写和阅读代码时,你经常会发现组合了几种运算的表达式。了解这些表达式的执行顺序非常重要(否则,你可能会对结果感到惊讶) 因为 Java 有很多操作,每个操作都在一个特殊的表中被分配了一个位置:运算符优先级
运算符 | 优先级 |
---|---|
后缀 | expr++ expr-- |
一元运算符 | ++expr --expr +expr ~ ! |
乘法 | * / % |
相加 | + - |
移位 | << >> >>> |
关系 | < > <= >= instanceof |
相等 | == != |
按位与 | & |
按位异或 | ^ |
按位或 | | |
逻辑与 | && |
逻辑或 | || |
三元运算符 | ? : |
赋值 | = += -= *= /= %= &= ^= |= <<= >>= >>>= |
int x = 6 - 4/2;
那么将首先执行除法运算 (4/2)。尽管位置在第二位,但其优先级更高。
圆括号和方括号表示最大优先级。你可能还记得在学校的时候学习过。
例如,如果将它们添加到表达式中
int x = (6 - 4)/2;
然后首先执行减法,因为它是用括号括起来的。
boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
例如:
boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
该表达式将按如下方式执行:- 4/2 = 2
boolean x = 6 - 2 > 3 && 12*12 <= 119;
- 12*12 = 144
boolean x = 6 - 2 > 3 && 144 <= 119;
- 6-2 = 4
boolean x = 4 > 3 && 144 <= 119;
接下来,执行比较运算符:- 4 > 3 = true
boolean x = true && 144 <= 119;
- 144 <= 119 = false

boolean x = true && false;
最后,与运算符 (&&) 将在最后执行。
boolean x = true && false;
boolean x = false;
例如,加法 (+) 运算符的优先级高于 !=(不等)比较运算符;
因此,在表达式中
boolean x = 7 != 6+1;
将首先执行 6+1 运算,然后执行 7 != 7 检查(计算结果为假),最后将结果 (false) 赋值给变量 x(赋值运算一般在所有运算符中优先级最低;见表)。
唷!这是一个很大的教训,但你做到了!如果你没有完全理解本课程或之前的课程,请不要担心。将来我们会不止一次地谈到这些话题。
一些关于逻辑和数字运算的 CodeGym 课程。我们不会很快谈到这些内容,但你现在读一读也无妨。
GO TO FULL VERSION