Java 中的运算符

Java 中的运算符可以这样分为六类:

  1. 算数运算符+-*/%++--
  2. 关系运算符==!=<<=>>=
  3. 逻辑运算符&&||!^&|
  4. 位运算符&|~^<<>>>>>
  5. 赋值运算符=+=-=*=/=%=&=|=^=<<=>>=>>>=
  6. 其他运算符.[]()?:instanceof

算数运算符

算数运算符分为一元运算符二元运算符

一元运算符

一元运算符只有一个操作数,其操作符为:正 +、负 -、自加 ++、自减 -- 这四个,其中自增 ++ 和自减 -- 又分两种情况:

  • 用于数值变量之前:在赋值操作中,先对被 ++-- 操作变量值先加 1 或者先减 1,然后在进行其他的操作。
  • 用于数值变量之后:在赋值操作中,先用被 ++-- 的操作变量值进行其他的操作,然后在对其值加 1 或者减 1。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int a = 10;
int b = +a;
int c = -a;
int d = -c;
System.out.println("a = " + a); // 输出:a = 10
System.out.println("b = " + b); // 输出:b = 10
System.out.println("c = " + c); // 输出:c = -10
System.out.println("d = " + d); // 输出:d = 10

// ++a:先让 a 的值 +1 改变 a 的值然后再执行输出语句
a = 10;
System.out.println(++a); // 输出:11
System.out.println(a); // 输出:11

// 上面三行代码等同于下面四行代码:
a = 10;
a = a + 1;
System.out.println(a); // 输出:11
System.out.println(a); // 输出:11

// ------分割线------

// a++:先执行了输出语句然后再让 a 的值 +1 改变 a 的值
a = 10;
System.out.println(a++); // 输出:10
System.out.println(a); // 输出:11

// 上面三行代码等同于下面四行代码:
a = 10;
System.out.println(a); // 输出:10
a = a + 1;
System.out.println(a); // 输出:11

一元运算符和前后的操作数之间有空格,可能在有些编译器下编译时会出错。

二元运算符

二元运算符则需要两个操作数(即符号两边都需要有操作数),其操作符为:加 +、减 -、乘 *、除 / 和 取余(取模) % 这五个,+-*/ 完成加减乘除基本的四则运算,% 是求两个数相除后的余数,运算规则和数学运算基本相同,在算数运算中,计算时按照从左向右的顺序计算,乘除和求余优先于加减,有括号先计算括号里面的,可以参考运算符优先级。不同的是,程序中的乘运算符不可省略,在数学中可写为 y=2x 而程序中必须写为 y=2*x。当二元运算的两个操作数的数据类型不同时,运算结果的数据类型和参与运算的操作数的数据类型中精度较高(或位数较长)一致。

示例代码:

1
2
3
4
5
6
7
8
int a = 10;
int b = 6;
System.out.println("a + b = " + (a + b)); // 输出:16
System.out.println("a - b = " + (a - b)); // 输出:4
System.out.println("a * b = " + (a * b)); // 输出:60
System.out.println("a / b = " + (a / b)); // 输出:1
System.out.println("a / b = " + (a * 1.0 / b)); // 输出:1.6666666666666667
System.out.println("a % b = " + (a % b)); // 输出:4

关系运算符

关系运算符用于比较两个数值之间的大小,其运算结果为一个逻辑类型(boolean 布尔类型)的数值,其操作符为:等于 ==、不等于 !=、小于 <、小于等于 <=、大于 > 和 大于等于 >= 这六个。

示例代码:

1
2
3
4
5
6
7
8
int a = 10;
int b = 16;
System.out.println("a == b:" + (a == b)); // 输出:a == b:false
System.out.println("a != b:" + (a != b)); // 输出:a != b:true
System.out.println("a < b:" + (a < b)); // 输出:a < b:true
System.out.println("a <= b:" + (a <= b)); // 输出:a <= b:true
System.out.println("a > b:" + (a > b)); // 输出:a > b:false
System.out.println("a >= b:" + (a >= b)); // 输出:a >= b:false

逻辑运算符

逻辑运算符要求操作数的数据类型为逻辑类型(boolean 布尔类型),其运算结果也是逻辑类型(boolean 布尔类型)的值,其操作符为:与 &&、或 ||、非 !、异或 ^、与 &、和 或 | 这六个。

示例代码:

1
2
3
4
5
boolean a = true;
boolean b = false;
System.out.println("a && b = " + (a && b)); // 输出:a && b = false
System.out.println("a || b = " + (a || b)); // 输出:b = a || b = true
System.out.println("a ^ b = " + (a ^ b)); // 输出:a ^ b = true

逻辑运算符的真值表

A B A && B A || B !A A ^ B A & B A | B
true true true true false false true true
true false false true false true false true
false true false true true true false true
false false false false true false false false
  • &、&&:A 与 B 均为 true 则结果为 true,否则结果为 false。
  • |、||:A 与 B 其中一个为 true 则结果为 true,否则结果为 false。
  • !:A true 则结果为 false,否则结果为 true。
  • ^:A 与 B 均为 true 或 false 即 A 与 B 结果相同时结果为 false,否则结果为 true。

其中 &&& 看起来有同样的效果都表示||| 看起来也有同样的效果都表示,他们的运算规则也基本相同,&| 运算是把逻辑表达式全部计算完,而 &&|| 运算具有短路计算功能。在程序设计时使用 &&||,不建议使用 &|

对于 & 来说,如果左侧条件为 false,也会计算右侧条件的值,而对于 && 来说,如果左侧的条件为 false,则不计算右侧的条件,这种现象被称作短路现象。

位运算符

位运算实际是将操作数转换成二进制表示方式,然后将两个二进制操作数对象从低端位(最右边)到高位对齐,每位进行位运算,其操作数和运算结果都是整型值(byte、short、int、long),可以是有符号的也可以是无符号的,其中位运算符又可以分为位逻辑运算符位移运算符,其运算符为:位与 &、位或 |、位异或 ^、位非 ~、左移 <<、右移 >> 和 无符号右移(0填充的右移) >>> 这七个。

位运算符参照表

运算符 名称 示例 说明
& 位与 60 & 13 = 12 把 60 和 13 按位求与
| 位或 60 | 13 = 61 把 60 和 13 按位求或
^ 位异或 60 ^ 13 = 49 把 60 和 13 按位求异或
~ 位非 ~60 = -61 把 60 按位求非
<< 左移 60 << 2 = 240 把 60 的各位左移 2 位
>> 右移 60 >> 2 = 15 把 60 的各位右移 2 位
>>> 无符号右移 60 >>> 2 = 15 把 60 的各位右移 2 位,左边填 0

位逻辑运算符

位运算中的逻辑运算符:位与 &、位或 |、位异或 ^ 和 位非 ~逻辑运算的相应操作的真值表完全相同,其差别只是位运算操作的操作数和运算结果都是二进制整数,而逻辑运算相应操作的操作数和运算结果都是逻辑类型(boolean 布尔类型)的值。

位逻辑运算符参照表

A B A & B A | B A ^ B ~A
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
&:其中一个为 0 结果为 0 两个都为 1 时结果为 1 否则为 0

0011 1100 = 60 操作数1
0000 1101 = 13 操作数2
-------------- 按位求与
0000 1100 = 12 结果
*/
System.out.println("60 & 13 = " + (60 & 13)); // 输出:60 & 13 = 12

/*
|:两个中有一个为 1 结果为 1 否则为 0

0011 1100 = 60 操作数1
0000 1101 = 13 操作数2
-------------- 按位求或
0011 1101 = 61 结果
*/
System.out.println("60 | 13 = " + (60 | 13)); // 输出:60 | 13 = 61

/*
^:两个都为 0 或 都为 1 即两个一样时结果为 0 否则为 1

0011 1100 = 60 操作数1
0000 1101 = 13 操作数2
-------------- 按位求异或
0011 0001 = 49 结果
*/
System.out.println("60 ^ 13 = " + (60 ^ 13)); // 输出:60 ^ 13 = 49

/*
~:为 0 时结果为 1 为 1 时结果为 0

0011 1100 = 60 初始值
--------------- 按位求非
1100 0011 = -61 结果
*/
System.out.println("~60 = " + (~60)); // 输出:~60 = -61

位移运算符

位移运算符:左移 <<、右移 >> 和 无符号右移 >>>

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
<<:左移是将一个二进制操作数对象按指定的移动位数向左移,左边(高位端)溢出的位数被丢弃,
右边(低端位)的空位用 0 补充,运算结果相当于乘以 2 的幂。

0011 1100 = 60 初始值
--------------- 左移 2 位
1111 0000 = 240 结果
*/
System.out.println("60 << 2 = " + (60 << 2)); // 输出:60 << 2 = 240

/*
>>:右移是将一个二进制操作数对象按指定的移动位数向右移,右边(低位端)溢出的位数被丢弃,
左边(高端位)的空位用符号位补充,正数的符号位为 0 ,负数的符号位为 1 ,运算结果相当于除以 2 的幂。

0011 1100 = 60 初始值
-------------- 右移 2 位
0000 1111 = 15 结果
*/
System.out.println("60 >> 2 = " + (60 >> 2)); // 输出:60 >> 2 = 15

/*
11111111 11111111 11111111 11000100 = -60 初始值
----------------------------------------- 右移 2 位,前面补符号位 1
11111111 11111111 11111111 11110001 = -15 结果
*/
System.out.println("-60 >> 2 = " + (-60 >> 2)); // 输出:-60 >> 2 = -15

/*
>>>:无符号右移是将一个二进制操作数对象按指定的移动位数向右移,右边(低位端)溢出的位数被丢弃,
左边(高端位)的空位一律用 0 填充 ,正数运算结果相当于除以 2 的幂。

0011 1100 = 60 初始值
-------------- 无符号右移 2 位
0000 1111 = 15 结果
*/
System.out.println("60 >>> 2 = " + (60 >>> 2)); // 输出:60 >>> 2 = 15

/*
11111111 11111111 11111111 11000100 = -60 初始值
----------------------------------------- 无符号右移 2 位,前面补 0
00111111 11111111 11111111 11110001 = 1073741809 结果
*/
System.out.println("-60 >>> 2 = " + (-60 >>> 2)); // 输出:-60 >>> 2 = 1073741809

赋值运算符

赋值运算符是由二元算术运算符、逻辑运算符和位运算符加上一个等号 = 组合成的简捷运算符,可以简化一些常用表达式的书写。

Java 常见数据类型:

  • 类型①(整型):byteshortintlong
  • 类型②(非整形):doublefloat
  • 类型③(非数值类型):charboolean
  • 类型④(引用型数据类型):String

赋值运算符与其他运算符的简介使用方式:

运算符 用法 等同于 类型
+= a += b a = a + b ① || ② || ④
-= a -= b a = a - b ① || ②
*= a *= b a = a * b ① || ②
/= a /= b a = a / b ① || ②
%= a %= b a = a % b ① || ②
&= a &= b a = a & b ① || boolean
|= a |= b a = a | b ① || boolean
^= a ^= b a = a ^ b ① || boolean
<<= a <<= b a = a << b
>>= a >>= b a = a >> b
>>>= a >>>= b a = a >>> b

其他运算符

点运算符

点运算符 . 的功能有两个:一是引用类中成员,二是指示包的层次等级,示例代码:

1
2
int r = (int)(java.lang.Math.random() * 100);
System.out.println(r); //输出:16

括号运算符

扩号运算符分为两种:

  • 方括号 [] 是数组运算符,方括号 [] 中的数值是数组的下标,整个表达式就代表数组中该下标所在位置的元素值。
  • 圆括号 () 运算符用于改变表达式中运算符的优先级。

示例代码:

1
2
String[] name = {"z", "p", "p", "0", "1", "9", "6"};
System.out.println(name[(1 + 1)]); // 输出:p

括号运算符成对出现,缺一不可。

条件运算符

条件运算符也被称为三目运算符。该运算符至少有3个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
int a;
boolean b = true;
int x = -1, y = 0, z = -1;
a = b ? x : z;
System.out.println(a); // 输出:-1
// 判断表达式 b 是否成立,如果 b == true 则把 x 的值赋给 a;如果 b == false 则把 z 的值赋给 a
// 等同于下面的 if-else 语句:
if (b) {
a = x;
} else {
a = z;
}
System.out.println(a); // 输出:-1

上面提到说该运算符至少有3个操作数,也就是说可以有更多的操作数。以上面代码为例,其中的 b 为第一个操作数,x 为第二个操作数,z 为第三个操作数,如果我们将 操作数1 ? 操作数2 : 操作数3 视为一个整体,将其称为第四个操作数,照猫画虎,可以把第二个操作数换成第四个操作数,这时这个整体一共就有五个操作数,而原先的单个 if-else 就可以变成一个嵌套 if-(if-else)-else

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int a;
boolean m = true;
boolean n = true;
int x = -1, y = 0, z = 1;
a = m ? (n ? x : y) : z;
System.out.println(a); // 输出:-1

// 等同于下面的if-else if-else
if (m) {
if (n) {
a = x;
} else {
a = y;
}
} else {
a = z;
}
System.out.println(a); // 输出:-1

如果把第三个操作数换成第四个操作数,这时这个整体一共就有五个操作数,而原先的单个 if-else 就可以变成一个 if-else if-else

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int a;
boolean m = false;
boolean n = true;
int x = -1, y = 0, z = 1;
a = m ? x : (n ? y : z);
System.out.println(a); // 输出:0

// 等同于下面的if-else if-else
if (m) {
a = x;
} else if (n) {
a = y;
} else {
a = z;
}
System.out.println(a); // 输出:0

同理可以一直嵌套写下去,这样写虽然方便,可以节省一些代码量,但是可读性差,不建议多个嵌套使用,如果使用尽量写清楚注释。

对象运算符

对象运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型),其操作符为:instanceof

1
2
String name = "zpp0196";
System.out.println(s instanceof String); // 输出:true

如果运算符左侧变量所指的对象,是操作符右侧类或接口 (class/interface) 的一个对象,那么结果为真,很明显 name 是 String 的一个对象,所以返回 true。

如果被比较的对象兼容于右侧类型,该运算符仍然返回 true:

1
2
CharSequence c = new String();
System.out.println(c instanceof String); // 输出:true

运算符优先级

优先级 操作符 关联性
1 .()[] 从左到右
2 +-!~++-- 从右到左
3 */% 从左到右
4 +- 从左到右
5 <<>>>>> 从左到右
6 <<=>>=instanceof 从左到右
7 ==!= 从左到右
8 & 从左到右
9 ^ 从左到右
10 | 从左到右
11 && 从左到右
12 || 从左到右
13 ?: 从右到左
14 =+=-=*=/=%=&=|=^=~=<<=>>=>>>= 从右到左
15 , 从左到右