吃透Java操作符入门:分类差异+进制转换+原反补码 核心前置知识(Java&C对比)

重阳,来,我们把 Java 操作符 这个“最容易被低估却最常坑人”的基础彻底吃透。

重点覆盖:分类 + 优先级差异 + 位运算核心前置(进制/原码反码补码) + Java vs C 关键对比

目标:看完能手算任意表达式 + 面试/刷题/底层代码不再慌。

1. Java 操作符完整分类(2026 年视角,JDK 21+ 无大变化)

优先级组(从高到低)操作符结合性说明 / 常见坑点
1() [] . new ::左→右最高,括号最强
2expr++ expr–左→右后置自增/自减
3++expr –expr + – ! ~ (type)右→左前置 + 取负 + 逻辑非 + 按位取反 + 强制转换
4* / %左→右乘除取模
5+ –左→右加减(+ 还能字符串拼接)
6<< >> >>>左→右位移(>>> 是 Java 独有)
7< <= > >= instanceof左→右关系 + 类型判断
8== !=左→右相等(对象比较引用,值类型比较值)
9&左→右按位与(也可用于 boolean 逻辑与)
10^左→右按位异或
11左→右
12&&左→右短路逻辑与
13
14? :右→左三元运算符
15= += -= *= /= %= &= ^== <<= >>= >>>=右→左

最容易错的优先级记忆口诀(前6个最重要):

“单目算术位移,乘除加减,位移关系等,位与异或或,逻辑短路,三目赋值”

常见陷阱

  • a & b == c → 先算 b == c,再 a & 结果(因为 == 优先级高于 &)
  • -5 >> 1 vs -5 >>> 1(后面详解)
  • i = i++ + ++i;(未定义行为,千万别写!)

2. 位运算前置:原码、反码、补码(必懂!)

Java 中所有整数(byte/short/int/long)一律用补码表示

概念正数示例 (以 8 bit 为例)负数示例 (-5, 8 bit)特点 / 记忆法
原码+5 → 00000101-5 → 10000101最高位是符号位(0正1负),其余是绝对值
反码+5 → 00000101-5 → 11111010(符号位不变,其余取反)正数反码=原码,负数符号位不变其余取反
补码+5 → 00000101-5 → 11111011(反码+1)计算机实际存储的就是补码

关键性质(背下来!):

  • 正数的原码 = 反码 = 补码
  • 负数的补码 = 反码 + 1
  • 补码的补码 = 原码(绕一圈回来)
  • ~x(按位取反)其实是 -x-1(补码世界里的数学性质)
  • 例:~5 = -6(因为 00000101 → 11111010 → 补码转十进制 = -6)

为什么用补码?

加减法统一(不用区分正负数电路不同)
0 有唯一表示(不像原码有 +0 和 -0)

3. Java 位运算符详解 + 与 C 的核心差异

操作符含义Java 行为(int 示例)C/C++ 对应行为对比关键差异点
&按位与5 & 3 = 1 (0101 & 0011 = 0001)完全相同(纯位运算)
按位或53 = 7
^按位异或5 ^ 3 = 6相同
~按位取反(一元)~5 = -6相同(但 C 中 int 可能是 32/64 bit 实现依赖)无大差异
<<算术左移(带符号,无差异)5 << 2 = 20
-5 << 2 = -20
相同(左移不影响符号位)
>>算术右移(带符号)5 >> 2 = 1
-5 >> 2 = -2(符号扩展)
C 中 >> 对 signed int 是实现定义(多数编译器算术右移)Java 强制算术右移,C 可能逻辑右移(老编译器)
>>>逻辑右移(无符号)5 >>> 2 = 1
-5 >>> 2 = 1073741822
C/C++ 没有 >>>!右移 signed 通常算术,unsigned 才逻辑最大差异!Java 独有,解决负数右移问题

负数 >>> 演示(非常重要!)

int a = -5;           // 二进制:1111 1111 1111 1111 1111 1111 1111 1011
System.out.println(a >> 2);   // -2   (1111 1111 ... 1110  符号扩展)
System.out.println(a >>> 2);  // 1073741822 (0011 1111 ... 1110  最高位补0)

C 语言里想实现无符号右移,只能把变量转为 unsigned int 或 unsigned long。

4. 常见位运算经典用法(刷题/面试必备)

用途表达式示例说明
判断奇偶(n & 1) == 1最快判断奇数
取绝对值(不使用 Math)(n ^ (n >> 31)) – (n >> 31)经典位运算取 abs(仅 int/long 有效)
交换两数(不使用临时变量)a ^= b; b ^= a; a ^= b;经典面试题
求 2 的幂次方n & (n-1) == 0 && n > 0判断是否 2 的幂
统计二进制 1 的个数n &= (n-1) 循环直到 n==0Brian Kernighan 算法(最快)
取低 n 位x & ((1 << n) – 1)掩码取低 n 位
设置第 k 位为 1x= (1 << k)
设置第 k 位为 0x &= ~(1 << k)
翻转第 k 位x ^= (1 << k)

5. 快速自测题(建议现在算一算)

  1. -8 >> 3 的结果是?(十进制)
  2. -8 >>> 3 的结果是?(注意 int 32 位)
  3. 表达式: 8 + (-3) & 7 的值?(优先级陷阱)
  4. ~0 的值是多少?
  5. 如何用位运算实现 ×8(不写 *)?

答案稍后可以问我,或者自己 System.out.println() 验证。

重阳,位运算 + 补码 + 优先级这三块吃透后,后面集合、IO、多线程里的位标志、哈希计算、布隆过滤器、权限校验等都会轻松很多。

现在你最想:

  • 看更多经典位运算面试题?
  • 手写几个位运算算法?
  • 继续下一节(比如自动类型转换 & 强制转换的坑)?
  • 还是有具体代码想让我帮你分析为什么结果是这样?

随时说,我们继续冲~

文章已创建 4357

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部