09-运算符

nobility 发布于 2025-07-13 01-Java语言基础 3013 次阅读


运算符

运算符的分类

算数运算

符号 含义
+
-
*
/
% 取模(求余数)
++ 自增
-- 自减

关系运算

符号 含义
== 等于
!= 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于

逻辑运算

符号 含义
&& 与(AND)
∣∣ 或(OR)
! 非(NOT)

位运算

符号 含义
& 按位与
按位或
^ 按位异或
~ 按位取反
<< 按位左移
>> 按位右移(补符号位)
>>> 无符号按位右移(补 0)

赋值运算

符号 含义
= 简单赋值
+= 加后赋值
-= 减后赋值
*= 乘后赋值
/= 除后赋值
%= 取模后赋值
<<= 左移后赋值
>>= 右移后赋值
&= 按位与后赋值
^= 按位异或后赋值
∣= 按位或后赋值

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

符号 格式 含义
?: var = condition ? exp1 : exp2 如果 condition 为真返回 exp1 的值,否则返回 exp2 的值

instanceof 运算符

符号 格式 含义
instanceof result = obj instanceof clazz 检查 obj 对象是否是特定类 clazzclazz 子类的实例

运算符的优先级

优先级 运算符 类型 示例 结合性
1 .[]() 访问、调用 obj.method() 从左到右
2 !~+-++ -- 一元运算 -aa++ 从右到左
3 */% 算术运算(乘除模) a * b 从左到右
4 +- 算术运算(加减) a + b 从左到右
5 <<>>>>> 位移运算 a << 2 从左到右
6 <<=>>=instanceof 比较运算 a > bx instanceof Y 从左到右
7 ==!= 相等性比较 a == b 从左到右
8 & 位与 a & b 从左到右
9 ^ 位异或 a ^ b 从左到右
10 位或 a ∣ b 从左到右
11 && 逻辑与(短路) a && b 从左到右
12 ∣∣ 逻辑或(短路) a ∣∣ b 从左到右
13 ?: 条件(三元)运算符 a > b ? x : y 从右到左
14 =+=-=*=/=%=&=|=^=~=<<=  >>=>>>= 赋值运算 a = b, a += 3 从右到左
15 , 逗号运算 a = 1, b = 2 从右到左

🔔 记忆口诀:

括号调用先发言,单目正反紧相连。
乘除模后再加减,移位排名略靠前。
大小比较随其后,真假对比肩并肩。
先位与,再异或,然后才能是位或。
逻辑与,逻辑或,三目赋值在加逗。

结合性

运算符的结合性(Associativity)‌ 决定了当一个表达式中出现多个‌相同优先级‌的运算符时,它们的执行顺序是‌从左到右‌(左结合)还是‌从右到左‌(右结合)的。结合性只在运算符优先级相同时生效,优先级不同时则按优先级高低执行。

左结合(Left-associative):按从左到右的顺序计算。

int a = 5, b = 2, c = 3;
int sum = a + b - c;
// 等价于
int sum = (a + b) - c;

boolean a = false, b = true, c = false, d = true, e = false;
boolean bool = a && b || c && d || e;
// 等价于
boolean bool = ((a && b) || (c && d)) || e;

右结合(Right-associative):按从右到左的顺序计算。

int a = 5, b = 2, c = 3;
a = b = 5;
// 等价于
a = (b = 5)

boolean a = false, b = true, c = false, d = true, e = false;
boolean bool = a ? b : c ? d : e;
// 等价于
boolean bool = a ? b : (c ? d : e);

余数的正负

余数的正负只和表达式中的左半部分有关,例如:

// 结果为 1
int a = 7 % 3;

// 结果依旧为 1
int a = 7 % -3;

// 结果为 -1
int a = -7 % 3;

运算中的 a++++a

虽然 a++++a 都是自增运算符,但是执行时机并不同。

  • a 在前的后置自增 a++:先使用变量 a 的当前值参与运算,然后再将 a 的值加 1。
  • a 在后的前置自增 ++a:先将变量 a 的值加 1,然后再使用增加后的值参与运算。

示例

int a = 5;
// 因为 a 在前,所以先使用 a 的当前值参与运算
// 结果是:b 先变成是 5,然后 a 再变成 6
int b = a++;

int a = 5;
// 因为 a 在后,所以先将变量 a 的值加 1,在参与运算
// 结果是:a 先变成是 6,然后 b 才变成 6
int b = ++a;

复杂点的例子:

int m = 1;
int n = 1;
int sum = m++ + ++n - n-- - --m + n-- - --m;
// m++ 先使用 m 的当前值参与运算,再将 m 加 1,此时运算值 = 1,m = 2
// ++n 先将 n 加 1,然后再使用增加后的值参与运算,此时运算值 = 2,n = 2
// n-- 先使用 n 的当前值参与运算,再将 n 减 1,此时运算值 = 2,n = 1
// --m 先将 m 减 1,然后再使用减少后的值参与运算,此时运算值 = 1,m = 1
// n-- 先使用 n 的当前值参与运算,再将 n 减 1,此时运算值 = 1,n = 0
// --m 先将 m 减 1,然后再使用减少后的值参与运算,此时运算值 = 0,m = 0
// 最终结果:
// sum = 1 + 2 - 2 - 1 + 1 - 0 = 1
// m = 0
// n = 0

交换两个变量的值

使用临时变量

使用临时变量,最常用,最容易理解,推荐使用。

public class Main {  
    public static void main(String[] args) {  
        int a = 5, b = 10;  
        int temp = a;  
        a = b;  
        b = temp;  
        System.out.println("a = " + a + ", b = " + b);  
    }  
}

使用算数运算

可能会溢出,不推荐使用。

class Main {  
    public static void main(String[] args) {  
        int a = 5, b = 10;  
        a = a + b;  
        b = a - b;  
        a = a - b;  
        System.out.println("a = " + a + ", b = " + b);  
    }  
}

使用位运算

仅适用于整数,不推荐使用。

public class Main {  
    public static void main(String[] args) {  
        int a = 5, b = 10;  
        a = a ^ b;  
        b = a ^ b;  
        a = a ^ b;  
        System.out.println("a = " + a + ", b = " + b);  
    }  
}

德摩根定律

  • 第一定律:NOT (A AND B) 等价于 (NOT A) OR (NOT B)
  • 第二定律:NOT (A OR B)等价于(NOT A) AND (NOT B)

逻辑短路

在使用逻辑运算符(&&||)时,如果能够根据第一个操作数确定整个表达式的结果,就不再计算第二个操作数的现象。具体来说:

  • 逻辑与(&&)短路:当第一个操作数为 false 时,整个表达式结果必定为 false,此时程序不会计算第二个操作数。
  • 逻辑或(||)短路:当第一个操作数为 true 时,整个表达式结果必定为 true,此时不会计算第二个操作数。

这种特性在实际编程中非常有用,可以避免不必要的计算,提高代码执行效率,也可以防止空指针异常。

示例

int[] a = null;  
// 单独使用会抛出 NullPointerException 异常  
int len = a.length;  

// 如果 a != null 计算为 false,那么 a.length 就不会执行  
if (a != null && a.length > 0) {  
    System.out.println("&& 短路");  
}  
  
// 如果 a == null 计算为 true,那么 a.length 就不会执行  
if (a == null || a.length <= 0) {  
    System.out.println("|| 短路");  
}

如果在某些情况下可能需要避免短路的发生,那么可以使用单个的 &| 路基运算符,它们总是会计算两个操作数。

当条件表达式中包含必须执行的副作用代码时(比如修改变量、I/O 操作等),短路就可能会跳过后续操作从而导致状态不一致。

示例

int[] a = null;  
// 即使 a != null 计算为 false,但是 a.length 依旧会执行,从而抛出 NullPointerException 异常  
if (a != null & a.length > 0) {  
    System.out.println("&& 短路");  
}  
  
// 即使 a 为 null,但是 a.length 依旧会执行,从而抛出 NullPointerException 异常  
if (a == null | a.length <= 0) {  
    System.out.println("|| 短路");  
}
加油啊!即便没有转生到异世界,也要拿出真本事!!!\(`Δ’)/
最后更新于 2025-07-13