Java移位运算符不溢出而是按位宽取模截断高位:int右操作数对32取模,long对64取模;有符号右移>>负数补1,无符号右移>>>负数变大正数;边界值如32、64易致逻辑错误。

Java移位运算符不会“溢出”,但会静默丢弃高位
Java中<<、>>、>>>对int或long操作时,**不抛异常、不报错、不截断值域**,而是按位宽取模后直接截断高位——这不是溢出,是定义行为。比如int是32位,1 << 35等价于1 << (35 % 32)即1 << 3,结果是8。
-
int移位时,右操作数自动对32取模(value % 32),long则对64取模 - 负数左移(如
-1 << 1)结果仍是补码表示的负数,不是“变正”或“溢出报错” - 写
i << 32对int来说等于i << 0,也就是原值——这点常被忽略,导致循环移位逻辑出错
有符号右移>>在负数上会补1,不是简单除2
对负数用>>,高位补的是符号位(1),不是0。所以-8 >> 1是-4,没错;但-1 >> 1是-1(0xFFFFFFFF >> 1 → 0xFFFFFFFF),不是0。它模拟的是“向下取整的算术右移”,不是数学除法。
-
-1 >> n对任意n > 0都还是-1,因为全1补1后仍是全1 - 想实现“向零取整”的右移(如
-5 / 2 == -2),不能直接用>>,得先转正再移再加符号 -
>>和/对正数等价,对负数不等价:比如-5 >> 1 == -3,而-5 / 2 == -2
无符号右移>>>对负数会变成很大正数
>>>不管符号位,一律补0。所以int型负数经>>>后,高位补0,低32位不变,结果是一个很大的正数。例如-1 >>> 1是0x7FFFFFFF即2147483647。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
>>>只对int和long有意义;byte/short会先提升为int再运算,注意隐式类型提升陷阱 - 用
>>>提取高位字节时(如(i >>> 24) & 0xFF),必须确保操作的是int或long,否则提升后可能多出无效位 -
>>>不能用于“安全除2”,因为-1 >>> 1不是0.5取整,而是彻底改变了数值语义
边界测试要覆盖0、31/32、63/64这些关键位数
移位右操作数为0、32(int)、64(long)时行为特殊:它们触发取模归零,容易写出“以为移了但其实没动”的bug。测试时别只试1、2、16。
立即学习“Java免费学习笔记(深入)”;
- 对
int,测试i << 0、i << 31、i << 32、i << 33——后两者分别等价于i << 0和i << 1 - 对负
int,测-1 >> 31(结果-1)、-1 >>> 31(结果1)、-1 >>> 32(等价于>>> 0,还是-1) - 用
Integer.MIN_VALUE << 1验证是否得到0(是的,因为符号位被移出,高位补0,结果是0x80000000 << 1 = 0)
真正容易翻车的,不是大数字,而是那些刚好卡在32/64倍数上的移位数——它们让代码看起来“运行正常”,实则逻辑已偏移。

















