对于Java运算符的优先级,一直想根据自己所学习的和网络上的资料整理一份,今天终于得偿所愿, 所以分享给大家,如果有不足之处,还请斧正.
这篇文章涉及的计算机底层的原码,反码和补码,需要恶补的朋友可以看一下我另外一篇博文:计算机底层存储数据形式和运算,这篇文章默认你是在了解计算机底层存储的情况下才能学习.另外,一般我用一个字节来解释,除非必要,我才会用32位int来举例解释;
Java的运算符的优先级有以下14个级别:
优先级 | 运算符 | 结合性 | 说明 |
---|---|---|---|
1 | ()、[]、{} | 从左向右 | 表达式分组,数组索引和语句块 |
2 | !、-、~、++、-- | 从右向左 | 逻辑非,负号,非运算符,自加,自减 |
3 | *、/、% | 从左向右 | 相乘、相除、求余数 |
4 | +、- | 从左向右 | 相加、相减、字符串串联 |
5 | <<、>>、>>> | 从左向右 | 左位移、右位移、无符号右移 |
6 | <、<=、>、>=、instanceof | 从左向右 | 小于、小于或等于、大于、大于或等于、是否 为特定类的实例 |
7 | ==、!= | 从左向右 | 相等、不相等 |
8 | & | 从左向右 | 按位“与” |
9 | ^ | 从左向右 | 按位“异或” |
10 | | | 从左向右 | 按位“或” |
11 | && | 从左向右 | 短路与(逻辑“与”) |
12 | || | 从左向右 | 短路或(逻辑“或”) |
13 | ?: | 从右向左 | 条件运算符 |
14 | =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>= | 从右向左 | 混合赋值运算符 |
以上就是在Java中的运算符优先级,运算符按照计算的参数数目可以分成三种:
1.单目运算符,比如 !表达式;
2.双目运算符,比如 表达式1 + 表达式2;
3.三目运算符,唯一一个表达式1 ? 表达式2 : 表达式3;
那我们就对每一个优先级别的运算符逐一进行分析:
1.(),[],{}
(1).()可以提升表达式的运算优先级,比如
a + b * c 运算顺序是b * c 的结果再和 a 相加;
(a + b) * c 我们通过()提升优先运算的级别,先计算 a + b ,然后用它们计算的结果 * c;
(2).[]是数组的索引;
(3).语句块
2.!、-、~、++、--
(1).!代表逻辑非,! true 的结果是false,相反, ! false 的结果是true;
(2),-负号;
(3).~,位运算符,参数只能是int类型,这个是非运算符,针对于二进制运算,0变1,1变0,举个例子:
运算表达式: ~ 3
3的补码: 0000 0011
~3的运算结果: 1111 1100
由于这个结果最高位是1,所以是负数,也就是说现在得到的结果1111 1100是补码:
~3的补码: 1111 1100
~3的反码: 1111 1011
~3的原码: 1000 0100
所以最终的~ 3 的结果是-4;
(4).++,++其实分成前++和后++,例如
int a = 0;
int b = ++a;
int c = 0
int d = c++;
运算完成以后b的值是1,d的值是0;但a和c的值都是1;
(5).--,--和++类似
,例如
int a = 0;
int b = --a;
int c = 0
int d = c--;
运算完成以后b的值是-1,d的值是0;但a和c的值都是-1;
3.*、/、%
这里 * 和 / 大家都知道,主要说一下 / ,取模或者取余,说白了就是求余数.例如:
5 /2 的结果是1;
0 / 3 的结果是0
4.+、-
+和-,这里要说一下字符串的+是拼接的意思,例如:
String str1= "宁静";
String str2= "致远";
那么str1 + str2的结果就是"宁静致远"
5.<<、>>、>>>
这三个是位运算符,主要针对的计算机中存储的二进制数据,这是我今天讲的重点:
(1).<<,左移运算符,不分正负数,低位直接补0,例如:
对于正数: 52 << 2
52的二进制补码:0000 0000 0011 0100
向左移动两位后:0000 0000 1101 0000
结果:208
对于负数: -52 << 2
-52 的二进制原码 :1000 0000 0011 0100
-52 的二进制反码 :1111 1111 1100 1011
-52 的二进制补码 :1111 1111 1100 1100
左移两位后的补码:1111 1111 0011 0000
反码:1111 1111 0010 1111
原码:1000 0000 1101 0000
结果:-208
(2).>>,右移运算符,如果是正数,则高位补0;如果是负数,则高位补1,例如:
对于正数:52 >> 2
52的二进制补码:0000 0000 0011 0100
向右移动两位后:0000 0000 0000 1101
结果:13
对于负数:-52 >> 2
-52 的二进制原码 :1000 0000 0011 0100
-52 的二进制反码 :1111 1111 1100 1011
-52 的二进制补码 :1111 1111 1100 1100
右移两位后的补码:1111 1111 1111 0011
反码:1111 1111 1111 0010
原码:1000 0000 0000 1101
结果:-13
(2).>>>,表示无符号右移,也叫逻辑右移,如果是正数,则高位补0;如果是负数,则右移后高位同样补0,例如:
对于正数: 52 >>> 2
结果与 52 >> 2 相同;
对于负数: -52 >>> 2
注意:为了和实际输出的结果一样,我们必须采用java默认的Int存储长度,即4Byte.
-52 的二进制原码 :10000000 00000000 00000000 00110100
-52 的二进制反码 :11111111 11111111 11111111 11001011
-52 的二进制补码 :11111111 11111111 11111111 11001100
无符号右移后 :00111111 11111111 11111111 11110011
反码:11111111 11111111 11111111 11101011
补码:11111111 11111111 11111111 11101100
右移:00111111 11111111 11111111 11111011
结果:1073741811
6.<、<=、>、>=、instanceof
<、<=、>、>=、instanceof这些运算符的结果都是boolean类型的值,也就是说表达式输出的结果只是会true和false.所以这里不再赘述.
7.==、!=
同上
8.&
&,位运算符,按位“与” ,必须有两个参数,当同位上全为1时,显示1,否则,显示0,例如:
运算表达式: 7 & 4
7的补码: 0000 0111
4的补码: 0000 0100
7 & 4的运算结果: 0000 0100,结果是4
9.^
^,位运算符,按位“异或” ,必须有两个参数,当同位上不相同时,显示1,同位上相同时,显示0,例如:
运算表达式: 7 ^ 4
7的补码: 0000 0111
4的补码: 0000 0100
7 ^ 4的运算结果: 0000 0011,结果是3
10.|
|,位运算符,按位“或” ,必须有两个参数,当同位上不全为0时,显示1,全为0时,显示0,例如:
运算表达式: 7 | 4
7的补码: 0000 0111
4的补码: 0000 0100
7 | 4的运算结果: 0000 0111,结果是7
11.&&
&&,逻辑与运算符,必须有两个参数或者表达式,必须是比较运算符,只有当&&两边的表达式都是true时,结果才是true,否则是false,例如:
1 == 1 && 2 > 3,结果是true;
1 == 1 && 2 < 3,结果是false;
1 != 1 && 2 < 3,结果是false;
1 != 1 && 2 > 3,结果是false;
12.||
||,逻辑或运算符,必须有两个参数或者表达式,必须是比较运算符,只要有||两边的表达式都不全为false时,结果是true,否则是false,例如:
1 == 1 || 2 > 3,结果是true;
1 == 1 || 2 < 3,结果是true;
1 != 1 || 2 < 3,结果是true;
1 != 1 || 2 > 3,结果是false;
13.? :
表达式1 ? 表达式2 : 表达式3 ,唯一一个三元运算符,必须有三个参数或者表达式,第一个参数必须是Boolean结果,如果表达式1结果是true,返回表达式2,如果是false,返回表达式3,例如:
2 > 3 ? "正确" : "错误" 的结果是 "错误";
2 < 3 ? "正确" : "错误" 的结果是 "正确";
14.=、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>=
=是赋值运算符, +=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>=,都属于混合赋值运算符,我就以 *= 来进行演示,其余类似:
int a = 1;
int b = 2;
int c = 3;
a *= b 其实就相当于a = a * b;
嗯,很多人感觉一看就懂,别急,继续看:
a *= b + c其实相当于a = a * (b + c)
此外,就是逻辑&&和逻辑||的短路问题:
对于逻辑&& ,表达式1 && 表达式2,当表达式1的值是false的时候,表达式2不会再执行,直接返回false;
对于逻辑|| ,表达式1 || 表达式2,当表达式1的值是true的时候,表达式2不会再执行,直接返回true;