Java运算符 位移运算的特殊之处

今天在研究Java源码,BitSet.java时看到这样一段代码

// bitIndex 表示要操作的位的索引
public void set(int bitIndex) {
    if (bitIndex < 0)
        throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
    // wordIndex()用来求bitIndex索引是存在于哪个数组元素上
    int wordIndex = wordIndex(bitIndex);
    // 用于判断是否要扩充数组
    expandTo(wordIndex)
    // words[]用于表示位图,类型为long[]
    // 然后奇怪的点就来了,就是这个操作 1L << bitIndex
    words[wordIndex] |= (1L << bitIndex); // Restores invariants
    
    checkInvariants();
}

java使用一个long[]的数组来表示位图,一个long型元素占8个字节,也就是64bit。当要向位图中进行set操作的时候会根据参数bitIndex,求wordIndex,这个过程是把bitIndex >> 16相当于是 bitIdex / 64向下取整,做为words[]的下标,表示bitIndex所指的那一位在哪个元素上。那么问题来了,传的参数是int类型,并且在wordIndex()中没有对bitIndex进行赋值操作,所以我们的bitIndex不会发生变化,那么当bitIndex的值大于等于64的时候,执行1L << bitIndex应该会产生溢出,或者全为0 ,但结果并不是这样,来看下面的代码

System.out.println(1 << 0);  // 结果 1
System.out.println(1 << 1);  // 结果 2
System.out.println(1 << 2);  // 结果 4
System.out.println(1 << 31); // 结果 -2147483648
System.out.println(1 << 32); // 结果 1
System.out.println(1 << 33); // 结果 2
System.out.println(1 << 34); // 结果 4

可以看到,当对一个int类型的数进行左移操作时,假如移动位数超过了该类型定义的总位数,会自动进行取余操作1 << (bitIndex % 64),所以在上边的代码中不会出现溢出问题

我们再来看看 >>操作是不是也是一样的道理

System.out.println(0x40000000 >> 1);
System.out.println(0x40000000 >> 2);
System.out.println(0x40000000 >> 31);
System.out.println(0x40000000 >> 32);
System.out.println(0x40000000 >> 33);
System.out.println(0x40000000 >> 34);

/* 结果同样进行了取余操作 并且我还测试了 >>> 结果是一样的
536870912
268435456
0
1073741824
536870912
268435456
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值