那天我在公司加班。已经 11 点了,办公区只剩我和空调“嗡嗡嗡”地对视。正准备关电脑的时候,隔壁组的老王突然探过头来问我一句:
“小米,你知道位操作符吗?面试官刚问我,我差点没绷住。”
我愣了一下,咖啡刚喝到嘴里。
位操作符?这玩意儿就像公司仓库里的最底层管理员,平时谁都不太搭理它,但一到关键时刻,它能决定系统性能、生死存亡。
我跟老王说:“位操作符啊,你可以把它理解成在二进制世界里搬箱子、点灯泡、开关闸门的人。 ”
老王一脸懵。于是,这篇文章就诞生了。
什么是位操作符?先别急着写代码
在 Java、Python 这些高级语言里,我们平时操作的是:
- int
- long
- boolean
- 对象、集合、字符串
但在CPU 眼里,这些东西统统只有一个形态:0 和 1, 所以你可以把位操作符理解为:直接对“0 和 1”动手的工具
如果把一个整数想象成一排灯泡:
1 0 1 1 0 0 1 0
那么位操作符就是:
- 把某几盏灯关掉
- 把某几盏灯点亮
- 把整排灯向左挪
- 把整排灯向右挪
而 Java 和 Python,都支持这些操作,但性格完全不一样。
先来一张全景对比表(建议收藏)
在深入故事之前,我们先把 Java 和 Python 支持的位操作符放在一张表里:
先记住一句话:
Python 没有无符号右移,Java 有。
这是后面一个非常重要的分水岭。
按位与(&):两个仓库门,必须同时开
1、生活比喻
按位与,就像公司有两道门:
- 门 A 打开(1)
- 门 B 打开(1)
只有两道门都打开,你才能进仓库。 只要有一扇是关的(0),你就进不去。
2、二进制视角
规则只有一句话:同为 1,结果才是 1
3、Java 示例
结论: 在 & 这件事上,Java 和 Python 表现得像一对性格稳定的老员工。
按位或(|):只要有人开门就行
1、比喻一下
这次换成公司应急通道:
- 门 A 打开
- 门 B 打开
只要有一扇门是开的,你就能进。
2、二进制规则
3、Java 示例
4、Python 示例
按位异或(^):相同就打回,不同才通过
1、这是最像“程序员性格”的操作符
异或的规则非常“程序员”:你俩一样?那就算了。不一样?那我就要。
2、二进制规则
3、Java 示例
4、Python 示例
面试高频:不用临时变量交换两个数
1、Java示例
2、Python示例
当然,Python 更推荐:
但面试官想听的是位运算思想,不是语法糖。
按位取反(~):所有灯泡反着来
1、比喻
你可以把 ~ 理解成: “夜班管理员,把所有灯的状态反转一次”
开着的关掉,关着的打开。
2、Java 的坑:有符号整数
为什么是 -11?因为 Java 的 int 是 32 位有符号整数,最高位是符号位。
3、Python 的表现更“抽象”
Python 表面看起来一样,但底层模型不同:Python 的整数是“无限位补码模型”,这也是 Python 位操作最容易让 Java 程序员懵的地方。
左移(<<):整体搬家,每动一位乘 2
1、生活比喻
左移就像:整排仓库箱子往左挪一个位置,右边补空箱(0)
小结一句话:左移 n 位 = 乘以 2 的 n 次方
右移:Java 和 Python 真正分道扬镳的地方
1、Java:两个右移操作符
-
:保持负数特性
-
:直接当无符号数处理
3、Python:没有 >>>
Python 只有算术右移,而且由于整数无限位,行为和 Java 的 >>> 完全对不上。
4、一句话总结差异
Java 更贴近硬件,Python 更偏向数学模型。
什么时候你真的需要位操作符?
这是我经常被问的一句。真实场景包括:
- 权限系统(bit mask)
- 状态压缩
- 高性能计算
- 网络协议
- 底层框架 / 中间件
总结
写到这里,咖啡已经凉了。如果你让我用一句话总结 Java 和 Python 的位操作符差异,我会这么说:
Java 的位操作符,是“工程师思维”;
Python 的位操作符,是“数学抽象”。
Java 更接近 CPU、寄存器、补码;
Python 更追求一致性和表达能力。
你不一定天天写位运算,但当你理解它的时候,你对“程序如何运行”这件事,会突然通透很多。
END
如果你觉得这篇文章有点意思,或者你正在准备 Java / Python 面试,欢迎转发、收藏、在看。
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!