跳转至

3 运算符

算术运算符

算术运算符

算术运算符用于执行基本的数学运算。

运算符 描述 示例 结果
+ 加法 5 + 3 8
- 减法 5 - 3 2
* 乘法 5 * 3 15
/ 除法 5 / 3 1(整数除法)
% 取余(模运算) 5 % 3 2
++ 自增 int a=5; a++ a变为6
-- 自减 int a=5; a-- a变为4

注意:整数除法会截断小数部分,如需要精确结果应使用浮点数

自增自减

自增自减运算符会改变变量的值,分为前置和后置两种形式。

  • 前置:先改变变量的值,再使用变量的值
  • 后置:先使用变量的值,再改变变量的值
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
int i = 10;
i++; // 单独使用
System.out.println("i:" + i); // i:11

int j = 10;
++j; // 单独使用
System.out.println("j:" + j); // j:11

int x = 10;
int y = x++; // 赋值运算,++在后边,所以是使用x原来的值赋值给y,x本身自增1
System.out.println("x:" + x + ", y:" + y); // x:11, y:10

int m = 10;
int n = ++m; // 赋值运算,++在前边,所以是使用m自增后的值赋值给n,m本身自增1
System.out.println("m:" + m + ", m:" + m); // m:11, m:11

字符的“+”操作

char类型参与算术运算,使用的是计算机底层对应的十进制数值。需要我们记住三个字符对应的数值:

  • 'a' -- 97: a-z是连续的,所以'b'对应的数值是98,'c'是99,依次递加
  • 'A' -- 65: A-Z是连续的,所以'B'对应的数值是66,'C'是67,依次递加
  • '0' -- 48: 0-9是连续的,所以'1'对应的数值是49,'2'是50,依次递加
1
2
3
4
5
6
7
// 可以通过使用字符与整数做算术运算,得出字符对应的数值是多少
char ch1 = 'a';
System.out.println(ch1 + 1); // 输出98,97 + 1 = 98
char ch2 = 'A';
System.out.println(ch2 + 1); // 输出66,65 + 1 = 66
char ch3 = '0';
System.out.println(ch3 + 1); // 输出49,48 + 1 = 49

算术表达式中包含不同的基本数据类型的值的时候,整个算术表达式的类型会自动进行提升。

提升规则:

  • byte类型,short类型和char类型将被提升到int类型,不管是否有其他类型参与运算。

整个表达式的类型自动提升到与表达式中最高等级的操作数相同的类型

等级顺序:byte,short,char --> int --> long --> float --> double

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
byte b1 = 10;
byte b2 = 20;
// byte b3 = b1 + b2; // 该行报错,因为byte类型参与算术运算会自动提示为int,int赋值给byte可能损失
精度
int i3 = b1 + b2; // 应该使用int接收
byte b3 = (byte) (b1 + b2); // 或者将结果强制转换为byte类型
-------------------------------
int num1 = 10;
double num2 = 20.0;
double num3 = num1 + num2; // 使用double接收,因为num1会自动提升为double类型

tips: 正是由于上述原因,所以在程序开发中我们很少使用byte或者short类型定义整数。也很少会使用char类型定义字符,而使用字符串类型,更不会使用char类型做算术运算。

字符串的“+”操作

当“+”操作中出现字符串时,这个“+”是字符串连接符,而不是算术运算符。

1
System.out.println("SleePerwtm"+ 666); // 输出:SleePerwtm666

在”+”操作中,如果出现了字符串,就是连接运算符,否则就是算术运算。当连续进行“+”操作时,从左到右逐个执行。

1
2
3
4
System.out.println(1 + 99 + "斤SleePerwtm"); // 输出:100斤SleePerwtm
System.out.println(1 + 2 + "SleePerwtm" + 3 + 4); // 输出:3SleePerwtm34
// 可以使用小括号改变运算的优先级
System.out.println(1 + 2 + "SleePerwtm" + (3 + 4)); // 输出:3SleePerwtm7

关系运算符

关系运算符用于比较两个值,返回布尔值(true/false)。

运算符 描述 示例 结果
== 等于 5 == 3 false
!= 不等于 5 != 3 true
> 大于 5 > 3 true
< 小于 5 < 3 false
>= 大于等于 5 >= 5 true
<= 小于等于 3 <= 5 true

位运算符

位运算符对整数的二进制位进行操作。

运算符 描述 示例(5=101, 3=011) 结果
& 按位与 5 & 3 1(001)
| 按位或 5 | 3 7(111)
^ 按位异或 5 ^ 3 6(110)
~ 按位非 ~5 -6
<< 左移 5 << 2 20(10100)
>> 右移 5 >> 2 1(001)
>>> 无符号右移 -5 >>> 2 1073741822

逻辑运算符

逻辑运算符用于连接布尔表达式,返回布尔值。

运算符 描述 特点 示例
&& 逻辑与 短路运算 (5>3) && (2<4) → true
|| 逻辑或 短路运算 (5>10) || (2<4) → true
! 逻辑非 取反 !(5>3) → false

与C/C++相同,Java的逻辑与 && 和逻辑或 || 都有短路特性:&& 左侧为false时不计算右侧;|| 左侧为true时不计算右侧。

而 & 和 | 没有短路特性,无论左侧结果如何都会计算右侧。

1
2
3
4
5
int x = 3;
int y = 4;
System.out.println((x++ > 4) & (y++ > 5)); // 两个表达都会运算
System.out.println(x); // 4
System.out.println(y); // 5
1
2
3
4
5
int x = 3;
int y = 4;
System.out.println((x++ > 4) && (y++ > 5)); // 左边已经可以确定结果为false,右边不参与运算
System.out.println(x); // 4
System.out.println(y); // 4

赋值运算符

赋值运算符用于给变量赋值。

运算符 描述 示例 等效于
= 基本赋值 a = 5 -
+= 加后赋值 a += 3 a = a + 3
-= 减后赋值 a -= 3 a = a - 3
*= 乘后赋值 a *= 3 a = a * 3
/= 除后赋值 a /= 3 a = a / 3
%= 取余后赋值 a %= 3 a = a % 3
&= 按位与后赋值 a &= 3 a = a & 3
|= 按位或后赋值 a |= 3 a = a | 3
^= 按位异或后赋值 a ^= 3 a = a ^ 3
<<= 左移后赋值 a <<= 2 a = a << 2
>>= 右移后赋值 a >>= 2 a = a >> 2

注: 复杂的赋值运算符隐含了强制类型转换

1
2
3
short s = 10;
s = s + 10; // 此行代码报错,因为运算中s提升为int类型,运算结果int赋值给short可能损失精度
s += 10; // 此行代码没有问题,隐含了强制类型转换,相当于 s = (short) (s + 10);

条件运算符(三元运算符)

唯一的三目运算符,语法简洁的条件判断。

语法条件表达式 ? 表达式1 : 表达式2

  • 若条件为true,执行表达式1,返回表达式1的值
  • 若条件为false,执行表达式2,返回表达式2的值

示例

1
2
3
int a = 5, b = 3;
int max = (a > b) ? a : b;  // max的值为5
String result = (a % 2 == 0) ? "偶数" : "奇数";  // result为"奇数"

instanceof 运算符

用于检查对象是否为特定类(或其子类)的实例,返回布尔值。

语法对象 instanceof 类名

示例

1
2
3
4
5
6
String str = "Hello";
boolean isString = str instanceof String;  // true

Object obj = new Integer(10);
boolean isInteger = obj instanceof Integer;  // true
boolean isNumber = obj instanceof Number;    // true(Integer是Number子类)

在Java 16+中,instanceof还支持模式匹配,可直接进行类型转换