- 👑专栏内容:Java
- ⛪个人主页:子夜的星的主页
- 💕座右铭:前路未远,步履不停
目录
- 一、算术运算符
- 1、四则运算符
- 2、增量运算符
- 3、自增、自减运算符
- 二、关系运算符
- 三、关系运算符
- 1、逻辑与 `&&`
- 2、逻辑或`||`
- 3、逻辑非`!`
- 4、短路求值
- 四、位运算符
- 1、按位与 `&`
- 2、按位或`|`
- 3、按位取反`~`
- 4、按位异或`^`
- 五、移位运算符
- 1、左移`<<`
- 2、右移`>>`
- 3、无符号右移 `>>>`
- 六、条件运算符
- 七、运算符的优先级
又见面了!还记得小学学数学的时候,那是我第一次接触到运算符这一概念。当初,我自以为已经彻底了解它们,可如今,它们却在Java中展现出了不一样的面貌,不禁让我感到有些陌生。这些曾经最熟悉的符号如今却成了我最熟悉的陌生人。今天,让我们来重新认识一下这位“ 最熟悉” 的 “陌生人” 吧!
一、算术运算符
1、四则运算符
四则运算是指加、减、乘、除、取余这四种基本算术运算。在Java中,使用以下运算符进行四则运算:
- 加法运算符(+):将两个数相加
- 减法运算符(-) :将两个数相减
- 乘法运算符(*):将两个数相乘
- 除法运算符(/) :将两个数相除,结果为商
- 取余运算符 (%) :求两个数相除后的余数
int a = 20;
int b = 10;
System.out.println("a+b = " + (a + b));
System.out.println("a-b = " + (a - b));
System.out.println("a*b = " + (a * b));
System.out.println("a/b = " + (a / b));
System.out.println("a%b = " + (a % b));
四则运算符确实和小学数学的运算规则一样,但是这里还是有几点需要注意一下。
- 四则运算符都是二元运算符,使用时运算符必须要有左右两个操作数
int / int
结果还是int类型,而且会向下取整
3
/
2
3/2
3/2在数学中应该是1.5,但是在Java中输出结果为1。这就是因为int / int
会向下取整,即小数点之后数全部都被舍弃掉了。
-
做除法和取模时,右操作数不能为0
这个学过数学的都知道,因为在除法运算中,0不可以做除数。 -
取余运算符可以应用于整数和浮点数。当运算数都是整数时,结果也是整数,当运算数包含浮点数时,结果是浮点数。
- 两侧操作数类型不一致时,向更宽容的类型进行提升
+
的左侧是int
,右侧是double
,在加之前int
被提升为double
更宽容的类型,指的是能够容纳更广范围取值的数据类型。它们通常具有更大的取值范围或更高的精度。
Java中的类型提升规则如下表所示:
操作数类型 | 提升为 |
---|---|
byte | int |
short | int |
int | long |
int | 浮点类型 |
long | 浮点类型 |
float | double |
2、增量运算符
增量运算符操作完成后,会直接将操纵的结果赋值给左操作数。
int a = 1;
a += 2; // 相当于 a = a + 2
System.out.println(a); // 输出3
a -= 1; // 相当于 a = a - 1
System.out.println(a); // 输出2
a *= 3; // 相当于 a = a * 3
System.out.println(a); // 输出6
a /= 3; // 相当于 a = a / 3
System.out.println(a); // 输出2
a %= 3; // 相当于 a = a % 2
System.out.println(a); // 输出2
注意:只有变量才能使用该运算符,常量不能使用。
3、自增、自减运算符
自增运算符++
:是给变量的值+1
自减运算符--
:是给变量的值-1
前置递增 (++a
):在变量 a 前面使用 ++ 运算符。它的作用是先将变量的值加1,然后返回递增后的值。也就是说,表达式的值是递增后的结果。
后置递增 (a++
):在变量 a 后面使用 ++ 运算符。它的作用是先返回变量的当前值,然后再将变量的值加1。也就是说,表达式的值是递增前的结果。
注意:
- 如果单独使用,【前置++】和【后置++】没有任何区别
--
操作符给操作-1,与++
含义类似。- 如果混合使用,【前置++】先+1,然后使用变量+1之后的值,【后置++】先使用变量原来的值,表达式结束时给变量+1
- 只有变量才能使用自增/自减运算符,常量不能使用,因为常量不允许被修改
二、关系运算符
关系运算符主要有六个: ==
!= ``<
>
<=
>=
,其计算结果是 true
或者 false
。
注意:在Java中 =
表示赋值,而非相等,==
才是相等的含义。
int a = 10;
int b = 20;
System.out.println(a == b); // false
System.out.println(a != b); // true
System.out.println(a < b); // true
System.out.println(a > b); // false
System.out.println(a <= b); // true
System.out.println(a >= b); // false
是的,但是需要注意一点。当需要多次判断时,不能连着写,比如: 3 < a < 5 3 < a < 5 3<a<5,Java程序与数学在这里是有区别的。那如果我想表示 3 < a < 5 3 < a < 5 3<a<5,应该如何写呢?
三、关系运算符
1、逻辑与 &&
语法规则:表达式1 && 表达式2
,左右表达式必须是boolean
类型的结果。
回到上面的问题,既然在Java中不能连着写,那我想表示 3 < a < 5 3 < a < 5 3<a<5,应该如何写呢?
我们分析一下
3
<
a
<
5
3 < a < 5
3<a<5,这个表达式无非是想表示
a
>
3
a>3
a>3并且
a
<
5
a < 5
a<5 这两层意思。那我们就可以使用逻辑与运算符。a > 3 && a < 5
因为只有两个表达式都为真,结果才是真,只要有一个是假,结果就是假。
表达式1 | 表达式2 | 结果 |
---|---|---|
真 | 真 | 真 |
真 | 假 | 假 |
假 | 真 | 假 |
假 | 假 | 假 |
2、逻辑或||
语法规则:表达式1 || 表达式2
,左右表达式必须是boolean
类型的结果。
表达式1 | 表达式2 | 结果 |
---|---|---|
真 | 真 | 真 |
真 | 假 | 真 |
假 | 真 | 真 |
假 | 假 | 假 |
3、逻辑非!
语法规则:! 表达式
真变假,假变真。
表达式 | 结果 |
---|---|
真 | 假 |
假 | 真 |
int a = 1;
System.out.println(!(a == 1));
System.out.println(!(a != 1));
4、短路求值
&&
和 ||
遵守短路求值的规则
System.out.println(10 > 20 && 10 / 0 == 0);
System.out.println(10 < 20 || 10 / 0 == 0);
我们都知道, 计算 10 / 0
会导致程序抛出异常. 但是上面的代码却能正常运行, 说明 10 / 0
并没有真正被求值
注意:
-
对于
&&
,如果左侧表达式值为 false, 则表达式结果一定是 false, 无需计算右侧表达式 -
对于
||
,如果左侧表达式值为 true, 则表达式结果一定是 true, 无需计算右侧表达式 -
&
和|
如果表达式结果为boolean
时,也表示逻辑运算。但与&&
||
相比,它们不支持短路求值
四、位运算符
先别着急晕,如果说前面的运算符都是最熟悉的陌生人,那么位运算符就是最陌生的陌生人,因为在我们学习编程之前,很少能接触到位运算。
在Java中,主要有四个位运算符:&
、|
、~
和^
,其中~
是一元运算符,其他三个是二元运算符。这些运算符允许我们对比特位进行操作,以进行各种位级运算和操作。
比特bit是二进制位的简称,一个二进制包含的信息量称为一比特bit。比特bit是计算机内部数据存储的最小单位。
1、按位与 &
位与运算符(&):将两个数的二进制表示的每一位进行逻辑与操作,只有当两个位都为1时,结果才为1。
int a = 10;
int b = 20;
System.out.println(a & b);
来猜猜这段代码的运行结果是什么。
没错!就是0,下面我来解释一下。进行按位运算前,需要先把10 和20 转成二进制, 分别为1010 和 10100
然后将两个数的二进制表示的每一位都进行与运行,只有当两个位都为1时,结果才为1。最后得到的结果就是0
2、按位或|
位或运算符(|):将两个数的二进制表示的每一位进行逻辑或操作,只有当两个位都为0时,结果才为0。
int a = 10;
int b = 20;
System.out.println(a | b);
3、按位取反~
取反运算符(~):将一个数的二进制表示的每一位取反,即0变为1,1变为0。
int a = 0xf;
System.out.printf("%x\n", ~a)
注意
-
0x
前缀的数字为 十六进制 数字,十六进制可以看成是二进制的简化表示方式。一个十六进制数字对应 4个二进制位 -
0xf
表示 10 进制的 15, 也就是二进制的 1111 -
printf
能够格式化输出内容, %x 表示按照十六进制输出 -
\n
表示换行符
4、按位异或^
位异或运算符(^):将两个数的二进制表示的每一位进行逻辑异或操作,只有当两个位不同时,结果才为1。
int a = 0x1;
int b = 0x2;
System.out.printf("%x\n", a ^ b);
由于二进制的每一位只有0和1两个数,所以我们不妨列个表格。
a | b | a^b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
不难发现,两个操作数,相同为0 不同为1。 我们也可也这样理解:异或运算就是无进位相加。
什么意思呢?用我们熟悉十进制的角度来看,比如我需要计算5+5,如果正常情况下,我们的计算结果应该是10,10拆开来看,10的个位数是0,十位数是1,可以理解为是两个个位数为5相加后进一的结果。如果不进位那就应该是00。当然十进制中并没有这种运算。
位运算在刚开始接触的时候,确实会感到非常麻烦。但是计算机是以二进制方式进行运算和存储的,你可以理解成计算机只认识二进制,其他进制最后都需要转化成二进制计算机才能认识。而位运算是可以直接在这些二进制位上进行操作,其重要性可想而知。
五、移位运算符
移位运算符有三个: <<
>>
>>>
,都是二元运算符,且都是按照二进制比特位来运算
1、左移<<
左移运算符(<<):将一个数的二进制表示向左移动指定的位数,左移后右边补0。
int a = 0x10;
System.out.printf("%x\n", a << 1);
// 运行结果(注意, 是按十六进制打印的)
注意:
%x
是一个格式化字符串,用于在printf
函数中以十六进制形式打印变量的值。- 向左移位时,丢弃的是符号位,因此正数左移可能会编程负数
2、右移>>
右移运算符(>>):将一个数的二进制表示向右移动指定的位数,右移后左边补符号位,即正数补0,负数补1。
int a = 0x10;
System.out.printf("%x\n", a >> 1);
int b = 0xffff0000;
System.out.printf("%x\n", b >> 1);
// 运行结果(注意, 是按十六进制打印的)
3、无符号右移 >>>
无符号右移运算符(>>>):将一个数的二进制表示向右移动指定的位数,右移后左边补0,不考虑符号位。
int a = 0xffffffff;
System.out.printf("%x\n", a >>> 1);
// 运行结果(注意, 是按十六进制打印的)
注意:
-
左移 1 位, 相当于原数字 * 2。左移 N 位, 相当于原数字 * 2 的N次方
-
右移 1 位, 相当于原数字 / 2。右移 N 位, 相当于原数字 / 2 的N次方
-
由于计算机计算移位效率高于计算乘除,当某个代码正好乘除 2 的N次方的时候可以用移位运算代替
六、条件运算符
条件运算符只有一个:表达式1 ? 表达式2 : 表达式3
当 表达式1 的值为 true 时, 整个表达式的值为 表达式2 的值,当 表达式1 的值为 false 时, 整个表达式的值为 表达式3 的值。
// 求两个整数的最大值
int a = 10;
int b = 20;
int max = a > b ? a : b;
注意:
- 条件运算符能少用就少用,能不用就不用。
因为你写的代码不仅仅是给计算机看的,还要给人看。虽然条件运算符可以提供简洁和紧凑的代码。但是,过度使用条件运算符也会导致代码可读性和可维护性的下降。
七、运算符的优先级
在一条表达式中,各个运算符可以混合起来进行运算,但是运算符的优先级不同。
比如:*
和 /
的优先级要高于 +
和 -
,有些情况下稍不注意,可能就会造成很大的麻烦。
// 求a和b的平均值
int a = 10;
int b = 20;
int c = a + (b - a) >> 1;
System.out.println(c);
上述表达式中,由于 +
的优先级要高于 >>
, 因此a先和b-a的结果做加法,整体为20,最后再进行右移,因此结果为10。
Java运算符优先级表:
优先级 | 运算符 |
---|---|
1 | ++, – (后缀) |
2 | +, - (一元正号和一元负号), ~, ! |
3 | *, /, % |
4 | +, - |
5 | <<, >>, >>> |
6 | <, >, <=, >=, instanceof |
7 | ==, != |
8 | &, ^, | |
9 | && |
10 | || |
11 | ?: |
12 | =, +=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, ^=, |= |
不要害怕!这个表看看就得了,千万别背!虽然运算符之间是有优先级的,但是具体的规则我们不必记忆。只需要在可能存在歧义的代码中加上括号即可。
// 求a和b的平均值
int a = 10;
int b = 20;
int c = a + ((b - a) >> 1);
System.out.println(c);
今天就说这么多啦!希望运算符这个最熟悉的陌生人从今以后能成为你最亲密的伙伴。我后续会持续更新其他Java内容,请保持关注。