Java运算符
运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算。例如:1+2,其操作数是1和2,而运算符则是“+”。
算术运算符
算术运算符就是常见的加减乘除以及取余运算。它们的作用是和平常接触的数学运算相差不大。
运算符 | 名称 | 说明 |
---|---|---|
+ | 加 | 求 a + b 的和 |
- | 减 | 求 a - b 的差 |
* | 乘 | 求 a * b 的积 |
/ | 除 | 求 a / b 的商 |
% | 取余 | 求 a % b 的余数 |
值得注意的是除法运算:
int a = 1;
int b = 2;
System.out.println(a / b);
//执行结果
0
正常来说"1/2"的结果是0.5,但在Java中两个int
类型的数值进行除法运算得到的还是int
类型,所以就会对结果进行取整直接将小数部分舍弃。
int a = 1;
float b = 2f;
System.out.println(a / b);
//执行结果
0.5
将任意一个变量的数据类型改为浮点型的时候,执行结果就变成了0.5,因为此时的进行运算的变量是两个不同的数据类型,此时会首先进行数据类型的转换,会把int
类型的a
变量转换为和b
变量相同的float
类型,之后再进行运算,得到的结果也是float
类型自然就可以表示小数了。也说明了浮点数之间也可以进行除法运算。
int a = 1;
int b = 0;
System.out.println(a / b)
//执行结果
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Test.main(Test.java:5)
还有就是这里的除法运算和数学的除法运算一样,0是不能作为除数的。
赋值运算符
基础的赋值运算符就是"=",它的优先级低于其他的运算符,所以对于该运算符往往最后才读取。
基础语法格式:
变量名称 = 表达式
Java中"变量名称"和"表达式"的数据类型必须相匹配,否则则需要将其转化为相应的数据类型。
赋值运算符和其他运算符一起使用时,可以实现多种不同效果的赋值运算。如,算术运算符和赋值运算符结合组成复合运算符
运算符 | 说明 | 示例 | 结果 |
---|---|---|---|
+= | 将变量的值和表达式的值进行加法运算,得到结果之后,再将结果赋值给变量。 | int a = 5; a += 2; | a = 7 |
-= | 将变量的值和表达式的值进行减法运算,得到结果之后,再将结果赋值给变量。 | int a = 5; a -= 2; | a = 3 |
*= | 将变量的值和表达式的值进行乘法运算,得到结果之后,再将结果赋值给变量。 | int a = 5; a *= 2; | a = 10 |
/= | 将变量的值和表达式的值进行除法运算,得到结果之后,再将结果赋值给变量。 | int a = 5; a /= 2; | a = 2 |
%= | 将变量的值和表达式的值进行取余运算,得到结果之后,再将结果赋值给变量。 | int a = 5; a %= 2; | a = 1 |
其实就是因为"="的优先级低于其他运算符,所以就是先进行其他运算符的运算再进行赋值。a += 2;
等价于a = a + 2;
这非常好理解,其他也是同理。
关系运算符
关系运算符,有6种关系,分别为小于、大于、小于等于、大于等于、等于和不等于。
运算符 | 名称 | 示例 | 说明 |
---|---|---|---|
< | 小于 | a < b | a 小于 b是为真返回true,否则为假返回false |
> | 大于 | a > b | a 大于 b是为真返回true,否则为假返回false |
<= | 小于等于 | a <= b | a 小于等于 b是为真返回true,否则为假返回false |
>= | 大于等于 | a >= b | a 大于等于 b是为真返回true,否则为假返回false |
== | 等于 | a == b | a 等于 b是为真返回true,否则为假返回false |
!= | 不等于 | a != b | a 不等于 b是为真返回true,否则为假返回false |
关系运算符的返回值都是boolean
类型,也就是说只有true
和false
两个值。
注意事项:
- >、<、>=、<= 的优先级相同,!=、== 也相同。但 >、<、>=、<= 的优先级高于!=、==。
- 关系运算符的优先级低于算术运算符。
- "==“和”="要注意区分。
逻辑运算符
逻辑运算符,是将语句连接成复杂的复合语句,来判断程序中的表达式是否成立。逻辑运算符的操作数和返回值都是boolean类型。
逻辑运算符用来表示日常交流中的“并且”,“或者”,“除非”等思想。
运算符 | 名称 | 示例 | 说明 |
---|---|---|---|
&& | 逻辑与(短路与) | x && y | 表达式 x 和表达式 y 都为true时才返回true,否则返回false |
|| | 逻辑或(短路或) | x || y | 表达式 x 和表达式 y 都为false时才返回false,否则返回true |
! | 逻辑非 | !x | 取表达式 x 结果的相反值,当 x 为true返回false,当 x 为false返回true |
& | 逻辑与 | x & y | 表达式 x 和表达式 y 都为true时才返回true,否则返回false |
| | 逻辑或 | x | y | 表达式 x 和表达式 y 都为false时才返回false,否则返回true |
"&&“和”||"的短路求值
System.out.println(10 > 20 && 10 / 0 == 0); //打印 false
System.out.println(10 < 20 || 10 / 0 == 0); //打印 true
众所周知,0是不能作为除数的,显然10/0
这个表达式是个错误的表达式,但是程序的执行结果并没有报错而是正常运行,说明10/0
并没有被执行。
对于"&&",当从左到右依次执行表达式时,当有其中一个表达式为false
时,说明整个表达式的结果一定为false
,无论后面的表达式是什么样的结果,也就无需再计算后续的表达式。
对于"||",当从左到右依次执行表达式时,当有其中一个表达式为true
时,说明整个表达式的结果一定为true
,无论后面的表达式是什么样的结果,也就无需再计算后续的表达式。
“&“和”|”
System.out.println(10 > 20 & 10 / 0 == 0); //程序抛出异常
System.out.println(10 < 20 | 10 / 0 == 0); //程序抛出异常
& 和 | 如果操作数为 boolean 的时候, 也表示逻辑运算. 但是和 && 以及 || 相比, 它们不支持短路求值.
注意事项:
逻辑运算符中,!的优先级最高,&&优先级高于||。!的优先级高于关系运算符,&&和||的优先级则低于关系运算符
短路与(&&)和短路或(||)能够采用最优化的计算方式,从而提高效率。在实际编程时,应该优先考虑使用短路与和短路或,且不推荐使用逻辑与(&)和逻辑或(|)。
位运算符
位运算符,是直接对操作数的二进制位进行运算。Java定义的位运算要求其操作数为整型或字符型,其运行结果为整型。
位运算符中的按位与、按位或和按位异或都是对操作数的二进制补码进行运算。这就需要了解计算机中的定点数的表达形式:原码、反码、补码。
原码
原码(true form)是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。
原码简单直观,通过符号位来表示正负,其他位则表示数值的大小。如,通过8位二进制数表示一个数,+1为00000001,-1则是10000001。
原码是不能直接参与运算的,可能会出现错误。如,1+(-1)=0,但使用二进制形式,00000001+10000001=10000010,将其换算成十进制则是-2。
反码
反码通常是用来由原码求补码或者由补码求原码的过渡码。反码就是原码符号位除外,其他位按位取反。其中还有些规定,正数的原码和反码是一致的,负数的反码才是除了符号位不变,其他位按位取反。
示例:对二进制原码10010取反,得到反码为11101。
补码
补码,将其原码除符号位外的所有位取反后加1。正数的原码和补码是一样的,负数的补码是原码按位取反后再加1。
示例:对二进制原码10010求补码,取反得反码为11101,再加1得11110。
Java中的位运算符分为两类:位逻辑运算符和移位运算符
位逻辑运算符:
运算符 | 名称 | 说明 |
---|---|---|
& | 按位与 | 对参与运算的操作数进行相与运算,对应二进制位都为1时才为1,否则为0 |
| | 按位或 | 对参与运算的操作数进行相或运算,对应二进制位都为0时才为0,否则为1 |
^ | 按位异或 | 对参与运算的操作数进行异或运算,对应二进制位不相同时才为1,否则为0 |
~ | 按位取反 | 对参与运算的操作数按位取反,即1变成0,0变成1 |
按位与 &
按位与运算符是对两个操作数进行相与运算,且参与的操作数是以补码的形式出现。
示例:5 & 9
写成二进制形式:00000101 & 00001001
,得到的结果则为00000001
,即5 & 9 = 1
。
int a = 5;
int b = 9;
System.out.println(a & b);
//执行结果
1
按位或 |
按位或运算符是对两个操作数进行相或运算,且参数的操作数是以补码的形式出现。
示例:5 | 9
写成二进制形式:00000101 | 00001001
,得到的结果为00001101
,即5 | 9 = 13
。
int a = 5;
int b = 9;
System.out.println(a | b);
//执行结果
13
按位异或 ^
按位异或运算符是对两个操作数进行异或运算,且参数的操作数是以补码的形式出现。
示例:5 ^ 9
写成二进制形式:00000101 ^ 00001001
,得到的结果为00001100
,即5 ^ 9 = 12
。
int a = 5;
int b = 9;
System.out.println(a ^ b);
//执行结果
12
按位取反 !
按位取反是单目操作符,对操作数按位取。
示例:~9
写成二进制形式:~00001001
,得到的二进制补码为11110110
,补码-1得到反码11110101
,反码取反得到原码10001010,即~9 = -10
。
在运算的时候是以补码的形式进行运算,而最终表现出来的是原码的形式。
移位运算符
移位运算符在程序设计中,是位操作运算符的一种。移位运算符可以在二进制的基础上对数字进行平移。按照平移的方向和填充数字的规则分为三种:<<(左移)、>>(右移)和>>>(无符号右移)。
运算符 | 名称 | 示例 | 结果 |
---|---|---|---|
<< | 左移 | 3 << 2 | 12 |
>> | 右移 | 11 >> 2 | 2 |
>>> | 无符号右移 | -11 >>> 2 | 1073741821 |
左移运算符 <<
左移运算符<<
,运算规则是,按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
示例:3 << 2
,将整数3向左移动2位。
int i = 3;
System.out.println(i << 2);
//执行结果
12
右移运算符 >>
右移运算符>>
,按二进制形式把所有的数字向右移动对应位移位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1。
示例:11 >> 2
,将整数11向右移动2位。
int i = 11;
System.out.println(i >> 2);
//执行结果
2
无符号右移 >>>
按二进制形式把所有的数字向右移动对应位数,低位移出(舍弃),高位的空位补零。对于正数来说和带符号右移相同,对于负数来说不同。
示例:-11 >> 2
,将整数11向右移动2位。
int i = -11;
System.out.println(i >> 2);
//执行结果
1073741821
位运算符也可以和赋值运算符组合成复合运算符。其实就是先将其进行位运算之后再赋值给变量。
运算符 | 示例 | 结果 |
---|---|---|
&= | num1 &= num2; | 等价于 num1 = num1 & num2; |
|= | num1 |= num2; | 等价于 num1 = num1 | num2; |
^= | num1 ^= num2; | 等价于 num1 = num1 ^ num2; |
~= | num1 ~= num2; | 等价于 num1 = num1 ~ num2; |
<<= | num1 <<= num2; | 等价于 num1 = num1 << num2; |
>>= | num1 >>= num2; | 等价于 num1 = num1 >> num2; |
>>>= | num1 >>>= num2; | 等价于 num1 = num1 >>> num2; |
条件运算符
条件运算符?:
,又称为三目运算符,其基础语法格式为:关系表达式 ? 表达式1 : 表达式2;
条件运算符的运算规则是根据关系表达式的布尔值结果来确定取值,当关系表达式为true是取表达式1的值,当关系表达式为false时,取表达式2的值。
示例:
int a = 10, b = 20, y;
System.out.println(y = a > b ? a : b);
//执行结果为
20
注意事项:
- 条件运算符的优先级低于关系运算符和算术运算符,高于赋值运算符。
- 关系表达式的结果必须为boolean类型。
- 当出现多个条件运算符,其结合性是右结合性。例:
y = a > b ? a : b < c ? b : c
,等价于y = a > b ? a : (b < c ? b : c)
先计算括号中表达式的结果,再根据结果运算y = a > b ? a : 结果
,再取值。
自增、自减运算符
在对Java变量做 加1 或 减1 处理时,可以使用自增++
运算符或自减--
运算符。++
与--
的作用就是使变量的值 增加1 或 减少1。操作数必须是整型或者浮点型。
++
和--
可以控制效果作用于运算之前还是之后,可通过将++
和--
前置或者后置来实现,具有很大的便利性。
运算符 | 名称 | 说明 | 示例 | 结果 |
---|---|---|---|---|
i++ | 后置++ | 先使用,后++ | int i = 1, y; y = i++; | i = 2,y = 1 |
++i | 前置++ | 先++,后使用 | int i = 1, y; y = ++i; | i = 2,y = 1 |
i-- | 后置– | 先使用,后– | int i = 1, y; y = i--; | i = 0,y = 1 |
--i | 前置– | 先–,后使用 | int i = 1, y; y = --i; | i = 0,y = 0 |
其他运算符
还有一些别的运算符如:()、[]、“.”、","等。
():一般用于方法的调用。
[]:用于声明数组,访问数组中的元素。
“.”(点运算符符):用于引用类的成员。
“,”(逗号运算符):可以把多个表达式用逗号联接起来,构成一个更大的表达式。
运算符的优先级
Java 语言中的运算符除了具有优先级之外,还有一个结合性的特点。当一个表达式中出现多种运算符时,执行的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的约束,以便确定是自左向右进行运算还是自右向左进行运算。
在一个表达式中可能包含多个有不同运算符连接起来的、具有不同数据类型的数据对象;由于表达式有多种运算,不同的结合顺序可能得出不同结果甚至出现错误运算错误,因为当表达式中含多种运算时,必须按一定顺序进行结合,才能保证运算的合理性和结果的正确性、唯一性。
优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。表达式的结合次序取决于表达式中各种运算符的优先级。优先级高的运算符先结合,优先级低的运算符后结合,同一行中的运算符的优先级相同
优先级 | 运算符 | 结合性 |
---|---|---|
1 | ()、[]、. | 从左向右 |
2 | !、~、++、–、+ (一元运算)、- (一元运算)、 | 从右向左 |
3 | *、/、% | 从左向右 |
4 | +、- | 从左向右 |
5 | <<、>>、>>> | 从左向右 |
6 | <、<=、>、>=、instanceof | 从左向右 |
7 | ==、!= | 从左向右 |
8 | & | 从左向右 |
9 | ^ | 从左向右 |
10 | | | 从左向右 |
11 | && | 从左向右 |
12 | || | 从左向右 |
13 | ?: | 从右向左 |
14 | = | 从右向左 |