运算符

算术运算符

就是小学数学的加减乘除,但有几个Java特有的坑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
public void testArithmetic() {
System.out.println("=== 算术运算符 ===");

int a = 10;
int b = 3;

System.out.println("a + b = " + (a + b)); // 13
System.out.println("a - b = " + (a - b)); // 7
System.out.println("a * b = " + (a * b)); // 30

// ⚠️ 整数除法:小数部分直接砍掉,不是四舍五入!
System.out.println("a / b = " + (a / b)); // 3,不是3.333...

// 想要小数结果?至少有一边是 double
System.out.println("a / (double)b = " + (a / (double) b)); // 3.3333...

// % 取余(取模):除法剩下的余数
System.out.println("a % b = " + (a % b)); // 1,因为 10÷3=3余1
}

整数除法的坑10 / 3 = 3 不是 3.33,Java会直接砍掉小数部分

取余 % :常用场景

判断奇偶:n % 2 == 0 就是偶数

判断能否整除:n % 3 == 0

循环取值:比如轮播图 index % 图片总数

自增自减(++ –)

这是面试和笔试的常客,一定要搞清楚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void testIncrementDecrement() {
System.out.println("=== 自增自减 ===");

int x = 5;

// ++x(前置):先加1,再使用
System.out.println("++x = " + (++x)); // 6,x先变成6,然后打印6

// x++(后置):先使用,再加1
x = 5; // 重置
System.out.println("x++ = " + (x++)); // 5,先打印5,然后x变成6
System.out.println("此时x = " + x); // 6

// 实际开发中的建议:
// 单独一行写 x++; 或 ++x; 效果一样,别搞花里胡哨的组合
// 面试才会问 int y = x++ + ++x; 这种东西,实际写这样的代码会被打
}

记忆口诀

++x(前置):先加后用,++在前面,加法优先

x++(后置):先用后加,++在后面,使用优先

实战建议for 循环里 i++++i 效果一样,大家习惯写 i++

赋值运算符

除了基本的 =,还有一堆偷懒的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void testAssignment() {
System.out.println("=== 赋值运算符 ===");

int score = 60;

score += 10; // 等价于 score = score + 10; 结果 70
System.out.println("score += 10 → " + score);

score -= 5; // 等价于 score = score - 5; 结果 65
System.out.println("score -= 5 → " + score);

score *= 2; // 等价于 score = score * 2; 结果 130
System.out.println("score *= 2 → " + score);

score /= 10; // 等价于 score = score / 10; 结果 13
System.out.println("score /= 10 → " + score);

score %= 5; // 等价于 score = score % 5; 结果 3
System.out.println("score %= 5 → " + score);
}
运算符 等价写法 说明
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 取余后赋值

隐藏的坑+= 会自动做强制类型转换

1
2
3
byte b = 10;
// b = b + 5; // ❌ 编译报错!b+5 的结果是 int,塞不回 byte
b += 5; // ✅ 没问题!+= 自带强制转换,等价于 b = (byte)(b + 5);

关系运算符(比较运算符)

比较两个值的大小关系,结果永远是 boolean(true 或 false)

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void testRelational() {
System.out.println("=== 关系运算符 ===");

int a = 10, b = 20;

System.out.println("a == b : " + (a == b)); // false
System.out.println("a != b : " + (a != b)); // true
System.out.println("a > b : " + (a > b)); // false
System.out.println("a < b : " + (a < b)); // true
System.out.println("a >= 10: " + (a >= 10)); // true
System.out.println("a <= 9 : " + (a <= 9)); // false
}
运算符 含义 示例
== 等于 5 == 5 → true
!= 不等于 5 != 3 → true
> 大于 5 > 3 → true
< 小于 3 < 5 → true
>= 大于等于 5 >= 5 → true
<= 小于等于 4 <= 5 → true

最容易犯的错=== 搞混

=赋值:把右边的值塞给左边

==比较:判断两边是否相等

比较字符串不能用 ==

1
2
3
4
5
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false!比较的是内存地址
System.out.println(s1.equals(s2)); // true!比较的是内容
// 记住:比较字符串永远用 .equals()

逻辑运算符

用来组合多个条件,做”且”、”或”、”非”的判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void testLogical() {
System.out.println("=== 逻辑运算符 ===");

int age = 25;
double salary = 8000;

// && (短路与):两个条件都满足才是 true
boolean canLoan = (age >= 18) && (salary >= 5000);
System.out.println("能贷款吗?" + canLoan); // true

// || (短路或):只要一个满足就是 true
boolean isWeekend = false;
boolean isHoliday = true;
boolean canRest = isWeekend || isHoliday;
System.out.println("能休息吗?" + canRest); // true

// ! (非):取反,true变false,false变true
boolean isRaining = false;
System.out.println("没下雨?" + !isRaining); // true
}
运算符 名称 说明 示例
&& 短路与 两边都true才true true && false → false
|| 短路或 一边true就true true || false → true
! 取反 !true → false

短路机制(重要)

&&:左边是 false,右边不执行(已经确定结果是false了,没必要看右边)

||:左边是 true,右边不执行(已经确定结果是true了)

1
2
3
4
5
6
7
// 短路的实际用途:防止空指针
String name = null;
// 如果 name 是 null,左边已经是 false,右边 name.length() 不会执行
// 这样就不会报 NullPointerException
if (name != null && name.length() > 0) {
System.out.println("名字是:" + name);
}

&&& 的区别

& 不短路:即使左边是false,右边也会执行(很少用)

&& 短路:左边false就不看右边了(实际开发永远用这个

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

if-else 的简写版,一行搞定简单判断

语法:条件 ? 值1 : 值2

条件为true → 返回值1

条件为false → 返回值2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void testTernary() {
System.out.println("=== 三元运算符 ===");

int score = 75;

// 等价于:if (score >= 60) result = "及格"; else result = "不及格";
String result = score >= 60 ? "及格" : "不及格";
System.out.println("成绩:" + result); // 及格

// 求两个数的最大值
int a = 10, b = 20;
int max = a > b ? a : b;
System.out.println("较大值:" + max); // 20

// 可以嵌套,但不推荐(可读性差)
int c = 15;
int maxOfThree = a > b ? (a > c ? a : c) : (b > c ? b : c);
System.out.println("三个数最大值:" + maxOfThree); // 20
// 上面那行不好读吧?所以超过两层判断就老老实实写 if-else
}

使用建议

简单的二选一 → 用三元运算符,代码更简洁

复杂判断或超过两层嵌套 → 老老实实写 if-else

位运算符(了解即可)

直接操作二进制位,日常业务开发很少用,但面试偶尔会考

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
@Test
public void testBitwise() {
System.out.println("=== 位运算符 ===");

int a = 5; // 二进制:0101
int b = 3; // 二进制:0011

// & 按位与:两位都是1才为1
System.out.println("5 & 3 = " + (a & b)); // 0001 → 1

// | 按位或:有一位是1就为1
System.out.println("5 | 3 = " + (a | b)); // 0111 → 7

// ^ 异或:两位不同才为1
System.out.println("5 ^ 3 = " + (a ^ b)); // 0110 → 6

// ~ 取反:0变1,1变0
System.out.println("~5 = " + (~a)); // -6

// << 左移:相当于乘以2的n次方
System.out.println("5 << 1 = " + (a << 1)); // 1010 → 10(5×2)
System.out.println("5 << 2 = " + (a << 2)); // 10100 → 20(5×4)

// >> 右移:相当于除以2的n次方
System.out.println("5 >> 1 = " + (a >> 1)); // 0010 → 2(5÷2取整)
}
运算符 名称 说明
& 按位与 两位都是1才为1
| 按位或 有一位是1就为1
^ 异或 两位不同才为1
~ 取反 0变1,1变0
<< 左移 相当于 ×2^n
>> 右移 相当于 ÷2^n

实际会遇到位运算的场景

权限控制:Linux文件权限 rwx 就是用位运算实现的(读=4,写=2,执行=1)

HashMap源码hash & (n-1) 用来计算数组下标,比取余更快

状态标记:用一个int的不同位来表示多个开关状态

运算符优先级

运算符太多记不住优先级?加括号就完事了

从高到低的大致顺序(不用死记,了解即可):

优先级 运算符 说明
1(最高) () 括号,永远最优先
2 ! ~ ++ -- 一元运算符
3 * / % 乘除取余
4 + - 加减
5 << >> 位移
6 < <= > >= 关系比较
7 == != 相等判断
8 & ^ | 位运算
9 && 逻辑与
10 || 逻辑或
11 ? : 三元运算符
12(最低) = += -= 赋值

实战唯一法则:看不清优先级就加括号,别赌!

1
2
3
4
5
// 不好:谁能一眼看出来这玩意儿先算什么?
int result = a + b * c >> 2 & d;

// 好:加了括号,意图一目了然
int result = ((a + (b * c)) >> 2) & d;

常见面试题

题1:不用第三个变量交换两个数

1
2
3
4
5
6
int a = 10, b = 20;
a = a ^ b; // a = 10 ^ 20
b = a ^ b; // b = (10 ^ 20) ^ 20 = 10
a = a ^ b; // a = (10 ^ 20) ^ 10 = 20
System.out.println("a=" + a + ", b=" + b); // a=20, b=10
// 原理:异或运算 x ^ x = 0,x ^ 0 = x

题2:判断一个数是不是2的幂

1
2
3
4
5
// 2的幂的二进制特点:只有一个1(如 8=1000, 16=10000)
// n & (n-1) 会把最低位的1消掉,如果结果是0说明只有一个1
public boolean isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
}

题3:short s = 1; s = s + 1;short s = 1; s += 1; 的区别

s = s + 1;编译报错s + 1 结果是int,不能直接赋给short

s += 1;正常+= 自带强制类型转换,等价于 s = (short)(s + 1);


上一章 目录 下一章
进制与编码 java基础 流程控制