当前位置: 首页 > news >正文

深入理解Java中的位运算

目录

一、位运算基础:认识二进制世界的操作符

1. 按位与(&)

2. 按位或(|)

3. 按位异或(^)

4. 按位非(~)

5. 左移(<<)

6. 右移(>>)

7. 无符号右移(>>>)

二、位运算的经典应用场景

1. 权限控制:用位掩码实现多权限管理

2. 数值交换:无需临时变量的高效交换

3. 奇偶判断:比取模运算更高效

4. 求绝对值:避免分支判断

5. 位计数:统计二进制中1的个数

三、位运算的注意事项

四、总结


位运算作为计算机最底层的运算方式,直接操作二进制位,具有极高的执行效率。在Java中,位运算虽然不常出现在业务代码中,但在框架设计、算法优化、数据压缩等场景中却有着不可替代的作用。

一、位运算基础:认识二进制世界的操作符

Java提供了7种位运算符,均作用于整数类型(byte、short、int、long),直接对二进制位进行操作。在了解具体运算符前,我们需要明确:Java中数值以补码形式存储,正数的补码与原码相同,负数的补码是其原码取反加1。

1. 按位与(&)

  • 运算规则:两个位都为1时,结果才为1,否则为0
  • 数学意义:可理解为"同时满足"的逻辑
  • 示例:
int a = 5;  // 二进制:0000 0101
int b = 3;  // 二进制:0000 0011
int c = a & b;  // 结果:0000 0001 → 十进制1

2. 按位或(|)

  • 运算规则:两个位只要有一个为1,结果就为1
  • 数学意义:可理解为"至少满足一个"的逻辑
  • 示例:
int a = 5;  // 0000 0101
int b = 3;  // 0000 0011
int c = a | b;  // 0000 0111 → 十进制7

3. 按位异或(^)

  • 运算规则:两个位不同时结果为1,相同时为0
  • 特殊性质:
    • 与0异或结果为其本身(a ^ 0 = a)
    • 与自身异或结果为0(a ^ a = 0)
    • 满足交换律和结合律(a ^ b ^ c = a ^ (b ^ c))
  • 示例:
int a = 5;  // 0000 0101
int b = 3;  // 0000 0011
int c = a ^ b;  // 0000 0110 → 十进制6

4. 按位非(~)

  • 运算规则:0变1,1变0(一元运算符)
  • 注意点:对正数操作会得到负数,因为符号位会被反转
  • 示例:
int a = 5;  // 0000 0101
int b = ~a;  // 1111 1010(补码)→ 十进制-6

5. 左移(<<)

  • 运算规则:将二进制位整体左移n位,右侧补0
  • 数学意义:相当于乘以2的n次方(不溢出情况下)
  • 示例:
int a = 5;  // 0000 0101
int b = a << 2;  // 0001 0100 → 十进制20(5×2²=20)

6. 右移(>>)

  • 运算规则:将二进制位整体右移n位,左侧补符号位(正数补0,负数补1)
  • 数学意义:相当于除以2的n次方(向下取整)
  • 示例:
int a = 20;  // 0001 0100
int b = a >> 2;  // 0000 0101 → 十进制5(20÷2²=5)int c = -20;  // 补码:1110 1100
int d = c >> 2;  // 1111 1011 → 十进制-5

7. 无符号右移(>>>)

  • 运算规则:将二进制位整体右移n位,左侧始终补0
  • 注意点:仅对32位int和64位long有效,会把负数当作正数处理
  • 示例:
int a = -20;  // 补码:1110 1100(简化为8位展示)
int b = a >>> 2;  // 0011 1011 → 十进制59(无符号处理)

二、位运算的经典应用场景

位运算的高效性(通常是CPU级别的操作)使其在特定场景中大放异彩,以下是几个典型应用:

1. 权限控制:用位掩码实现多权限管理

位运算非常适合实现"开关式"权限控制,每个二进制位代表一种权限状态(1表示拥有,0表示未拥有):

// 定义权限常量(每个常量是2的幂,确保二进制只有一位为1)
public class Permission {public static final int READ = 1 << 0;  // 0001 → 1public static final int WRITE = 1 << 1; // 0010 → 2public static final int EXECUTE = 1 << 2; // 0100 → 4public static final int DELETE = 1 << 3; // 1000 → 8// 检查是否拥有指定权限public static boolean hasPermission(int permissions, int target) {return (permissions & target) == target;}// 添加权限public static int addPermission(int permissions, int target) {return permissions | target;}// 移除权限public static int removePermission(int permissions, int target) {return permissions & ~target;}public static void main(String[] args) {int userPerms = READ | WRITE; // 拥有读写权限System.out.println(hasPermission(userPerms, READ)); // trueSystem.out.println(hasPermission(userPerms, EXECUTE)); // falseuserPerms = addPermission(userPerms, EXECUTE); // 增加执行权限userPerms = removePermission(userPerms, WRITE); // 移除写权限}
}

这种方式比使用集合或布尔值数组节省内存,且权限操作(增删查)效率极高。

2. 数值交换:无需临时变量的高效交换

利用异或的特性,可以不借助临时变量实现两个整数的交换:

public static void swap(int[] arr, int i, int j) {if (i != j) { // 避免自身异或导致值变为0arr[i] ^= arr[j];  // a = a ^ barr[j] ^= arr[i];  // b = b ^ (a ^ b) = aarr[i] ^= arr[j];  // a = (a ^ b) ^ a = b}
}

3. 奇偶判断:比取模运算更高效

判断一个数是奇数还是偶数,使用位运算比n % 2更高效:

// 二进制末位为1则是奇数
public static boolean isOdd(int n) {return (n & 1) == 1;
}

4. 求绝对值:避免分支判断

利用位运算可以实现无分支的绝对值计算(适用于32位int):

public static int abs(int n) {int mask = n >> 31;  // 正数mask为0,负数mask为-1(全1)return (n ^ mask) - mask;  // 负数时相当于~n + 1(取补码)
}

5. 位计数:统计二进制中1的个数

统计一个数的二进制表示中1的个数(汉明重量):

//  Brian Kernighan算法:每次清除最右边的1,直到数变为0
public static int countOneBits(int n) {int count = 0;while (n != 0) {n &= n - 1;  // 清除最右边的1count++;}return count;
}

三、位运算的注意事项

1.类型提升问题:对byte、short等类型进行位运算时,会先自动提升为int再运算,需注意结果类型转换

byte a = 0b11111111; // -1(byte类型)
int b = a & 0xFF; // 0x000000FF → 255(正确获取无符号值)

2.移位溢出问题:移位位数超过类型位数时,会进行取模处理(int取模32,long取模64)

int a = 1;
int b = a << 33; // 相当于1 << 1 → 2(33 % 32 = 1)

四、总结

位运算作为直接操作二进制的底层运算方式,在Java中虽然不常使用,但掌握它能让我们:

理解框架和JDK源码中复杂的位操作逻辑(如HashMap中的哈希计算)等

学习位运算的关键在于理解二进制的操作逻辑,多结合实际场景练习。


文章转载自:

http://32XN8gEh.cbnxq.cn
http://f9MMsOQp.cbnxq.cn
http://ypsXKNoI.cbnxq.cn
http://rDgNJxlp.cbnxq.cn
http://lgf4WmXS.cbnxq.cn
http://q0ok3hkB.cbnxq.cn
http://sGAlx6tF.cbnxq.cn
http://KMstCSqD.cbnxq.cn
http://ejYbp5iu.cbnxq.cn
http://5zRcfz4Z.cbnxq.cn
http://jvmqGpQP.cbnxq.cn
http://tTYAoLko.cbnxq.cn
http://VLG32EbP.cbnxq.cn
http://hPjvBNFX.cbnxq.cn
http://T6IL3fip.cbnxq.cn
http://6mL9q3oH.cbnxq.cn
http://AXNQT0fC.cbnxq.cn
http://gxMAWBtZ.cbnxq.cn
http://fblAzL4F.cbnxq.cn
http://tjXQGmn9.cbnxq.cn
http://RTXU18SV.cbnxq.cn
http://pcbNQVd3.cbnxq.cn
http://3QerYAwv.cbnxq.cn
http://YcnS3Bv5.cbnxq.cn
http://vFUccrHo.cbnxq.cn
http://Vonu8C42.cbnxq.cn
http://2HNoFxPr.cbnxq.cn
http://TK38mYRt.cbnxq.cn
http://h3W0QfSi.cbnxq.cn
http://lglTnKZe.cbnxq.cn
http://www.dtcms.com/a/377200.html

相关文章:

  • Docker 部署生产环境可用的 MySQL 主从架构
  • 设计模式-工厂方法原型模板方法外观
  • John the Ripper jumbo + HashCat 破解压缩密码 ubuntu amd GPU
  • 笔记 | ubuntu20.04离线安装Docker
  • 4.1.多线程JUC-什么是多线程?
  • 硅基计划4.0 算法 模拟
  • Android调用系统内置的UiAutomator工具实现自动化测试
  • vim 编辑器
  • RAG原理是什么?
  • 小白必看:AI智能体零基础搭建全攻略!
  • 品牌方与服务商布局 GEO 优化:差异化优势与商业价值落地路径​
  • 高防IP如何抵御CC攻击?2025年全面防护机制解析
  • Memory in LLM Agent
  • WebAssembly (WASM) 简介
  • Vue: 列表渲染 (v-for)
  • Python NumPy安装、导入与入门
  • Linux ip 命令使用指南
  • 【科研知识】常用细胞增殖检测方法
  • 微算法科技(NASDAQ: MLGO)基于阿基米德优化算法(AOA)的区块链存储优化方案
  • 国产双复旦微VU9P+ZYNQ7100-6U VPX板卡
  • 装备制造专用CRM销售系统推荐(8款)
  • 模块一 入门微服务
  • 安卓、Windows、macOS 应用开发技术栈与跨平台方案深度解析
  • 网页防篡改技术:原理、应用与安全保障
  • 热门资产管理软件有哪些?
  • 高效运用WMS系统,打造智慧仓储管理新核心
  • 【Ansible】实施任务控制知识点
  • Java算法题中的输入输出流
  • 10 写第一份 AI 产品 PRD
  • FDTD_Zemax