强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

05 - 运算符:算术、逻辑、位运算、三元

05 - 运算符:算术、逻辑、位运算、三元

算术运算符

运算符名称示例结果
+10 + 313
-10 - 37
*10 * 330
/10 / 33(整数除法截断)
%取模10 % 31
++自增i++ / ++ii = i + 1
--自减i-- / --ii = i - 1
public class ArithmeticDemo {
    public static void main(String[] args) {
        int a = 10, b = 3;

        System.out.println("加法: " + (a + b));    // 13
        System.out.println("减法: " + (a - b));    // 7
        System.out.println("乘法: " + (a * b));    // 30
        System.out.println("除法: " + (a / b));    // 3(整数除法)
        System.out.println("取模: " + (a % b));    // 1

        // 浮点除法
        double da = 10.0, db = 3.0;
        System.out.println("浮点除法: " + (da / db));  // 3.3333...

        // 自增前缀 vs 后缀
        int x = 5;
        int y = x++;  // y = 5, x = 6(先赋值后自增)
        int z = ++x;  // z = 7, x = 7(先自增后赋值)
        System.out.println("x=" + x + ", y=" + y + ", z=" + z);

        // 整数溢出
        int max = Integer.MAX_VALUE;     // 2147483647
        System.out.println("溢出: " + (max + 1));  // -2147483648

        // 除以零
        // int div = 10 / 0;           // ❌ ArithmeticException
        double d = 10.0 / 0.0;          // ✅ Infinity(不会抛异常)
        System.out.println("浮点除零: " + d);   // Infinity
    }
}

赋值运算符

运算符等价于示例
=-a = 10
+=a = a + ba += 5
-=a = a - ba -= 3
*=a = a * ba *= 2
/=a = a / ba /= 4
%=a = a % ba %= 3
&=a = a & ba &= 0xFF
|=a = a | ba |= 0x01
^=a = a ^ ba ^= mask
<<=a = a << na <<= 2
>>=a = a >> na >>= 1

⚠️ 复合赋值运算符会自动进行类型转换:byte b = 10; b += 5; 等价于 b = (byte)(b + 5);

比较运算符

运算符含义示例
==等于a == b
!=不等于a != b
>大于a > b
<小于a < b
>=大于等于a >= b
<=小于等于a <= b
instanceof类型检查obj instanceof String
public class ComparisonDemo {
    public static void main(String[] args) {
        // 基本类型:比较值
        int a = 10, b = 20;
        System.out.println(a == b);   // false
        System.out.println(a != b);   // true

        // 包装类陷阱
        Integer x = 128, y = 128;
        System.out.println(x == y);       // false!(比较引用)
        System.out.println(x.equals(y));  // true(比较值)

        // 字符串比较
        String s1 = new String("hello");
        String s2 = new String("hello");
        System.out.println(s1 == s2);       // false(不同对象)
        System.out.println(s1.equals(s2));  // true(值相等)
        System.out.println("hello" == "hello"); // true(字面量共享)

        // instanceof(JDK 16+ 模式匹配)
        Object obj = "Hello";
        if (obj instanceof String s) {
            System.out.println("长度: " + s.length()); // 无需强转
        }
    }
}

逻辑运算符

运算符含义特点
&&短路与左侧为 false 时,右侧不执行
||短路或左侧为 true 时,右侧不执行
!逻辑非取反
&逻辑与两侧都执行
|逻辑或两侧都执行
^逻辑异或不同为 true
public class LogicDemo {
    public static void main(String[] args) {
        // 短路求值
        int x = 0;
        // if (x != 0 && 10 / x > 1) { ... }  // 安全,短路
        // if (x != 0 & 10 / x > 1) { ... }    // ❌ ArithmeticException!

        // 三元运算符
        int score = 85;
        String grade = score >= 60 ? "及格" : "不及格";
        System.out.println(grade);  // 及格

        // 嵌套三元(不推荐太深)
        String level = score >= 90 ? "优秀"
                     : score >= 80 ? "良好"
                     : score >= 60 ? "及格"
                     : "不及格";
        System.out.println(level);  // 良好
    }
}

位运算符

运算符名称示例说明
&按位与0b1100 & 0b1010 = 0b1000都为 1 才为 1
|按位或0b1100 | 0b1010 = 0b1110有 1 就为 1
^按位异或0b1100 ^ 0b1010 = 0b0110不同为 1
~按位取反~0b1100 = ...00110 变 1,1 变 0
<<左移1 << 3 = 8左移 n 位 = ×2ⁿ
>>右移(带符号)-8 >> 2 = -2高位补符号位
>>>无符号右移-1 >>> 28高位补 0
public class BitwiseDemo {
    public static void main(String[] args) {
        int a = 0b11001010;  // 202
        int b = 0b10101100;  // 172

        System.out.println("a & b  = " + Integer.toBinaryString(a & b));  // 10001000
        System.out.println("a | b  = " + Integer.toBinaryString(a | b));  // 11101110
        System.out.println("a ^ b  = " + Integer.toBinaryString(a ^ b));  // 01100110
        System.out.println("~a     = " + Integer.toBinaryString(~a));

        // 位移运算
        System.out.println("1 << 4  = " + (1 << 4));   // 16
        System.out.println("16 >> 2 = " + (16 >> 2));  // 4

        // 实际应用:权限标志
        final int READ    = 0b001;  // 1
        final int WRITE   = 0b010;  // 2
        final int EXECUTE = 0b100;  // 4

        int permission = READ | WRITE;  // 赋予读写权限
        System.out.println("有读权限: " + ((permission & READ) != 0));     // true
        System.out.println("有执行权限: " + ((permission & EXECUTE) != 0)); // false

        // 切换权限
        permission ^= EXECUTE;  // 添加执行权限
        permission ^= READ;     // 移除读权限
        System.out.println("最终权限: " + Integer.toBinaryString(permission)); // 110
    }
}

位运算实用技巧

public class BitTricks {
    public static void main(String[] args) {
        // 判断奇偶(比 % 2 快)
        int n = 7;
        System.out.println((n & 1) == 0 ? "偶数" : "奇数");

        // 乘除 2 的幂
        System.out.println(5 << 1);   // 10(×2)
        System.out.println(5 << 3);   // 40(×8)
        System.out.println(40 >> 3);  // 5(÷8)

        // 不用临时变量交换两个数
        int x = 3, y = 7;
        x ^= y; y ^= x; x ^= y;
        System.out.println("x=" + x + ", y=" + y);  // x=7, y=3

        // 求绝对值(不考虑溢出)
        int val = -42;
        int abs = (val ^ (val >> 31)) - (val >> 31);
        System.out.println("绝对值: " + abs);  // 42
    }
}

运算符优先级

优先级运算符结合性
1() [] .左 → 右
2! ~ ++ -- +(正) -(负)右 → 左
3* / %左 → 右
4+ -左 → 右
5<< >> >>>左 → 右
6< <= > >= instanceof左 → 右
7== !=左 → 右
8&左 → 右
9^左 → 右
10|左 → 右
11&&左 → 右
12||左 → 右
13? :右 → 左
14= += -=右 → 左

💡 记忆口诀:单目 > 算术 > 移位 > 关系 > 位运算 > 逻辑 > 三元 > 赋值。拿不准就加括号!

⚠️ 注意事项

  1. 整数溢出不抛异常 — Java 整数溢出会默默回绕,使用 Math.addExact() 等方法可检测溢出。
  2. 浮点数不能用 == 比较 — 使用 Math.abs(a - b) < 1e-9Double.compare()
  3. >>> 是 Java 特有的 — 其他语言可能没有无符号右移操作符。
  4. 字符串拼接使用 + — 编译器会优化为 StringBuilder,但循环中应手动使用 StringBuilder

💡 技巧

  1. 检查 2 的幂

    boolean isPowerOfTwo = (n & (n - 1)) == 0 && n > 0;
    
  2. 位计数

    int bitCount = Integer.bitCount(0b10101010);  // 4
    
  3. 数字中 1 的个数(Brian Kernighan 算法)

    int count = 0;
    int n = 0b10101010;
    while (n != 0) { n &= (n - 1); count++; }
    

🏢 业务场景

  • 权限系统: 使用位运算实现 RBAC 权限管理,每个 bit 代表一种权限。
  • 分布式 ID: Snowflake 算法使用位移运算组合时间戳、机器 ID、序列号。
  • 网络编程: 子网掩码计算大量使用位运算。

📖 扩展阅读