Java 运算符易混点:、||、、| 与位运算到底差在哪

发布时间:2026/6/3 18:24:34
Java 运算符易混点:、||、、| 与位运算到底差在哪
Java 运算符易混点、||、、| 与位运算到底差在哪一、先问一句你在判断条件还是在处理二进制位二、 和 ||短路的意义是“右边可能不执行”三、 和 | 放在 boolean 上能用但不短路四、、|、^、~ 放在整数上逐位计算1. 按位与 2. 按位或 |3. 按位异或 ^4. 按位取反 ~五、移位运算移动的是二进制位六、优先级能加括号就别考验读者七、实战判断口诀 博主名称超级苦力怕 个人专栏《基本功修炼大全》 每一次思考都是突破的前奏每一次复盘都是精进的开始文章元信息适合读者Java 初学者、正在复习运算符和条件判断的后端入门读者前置知识Java 基本语法、boolean 表达式、整数二进制表示的基本概念如果你经常把 和 、|| 和 | 记混这篇从“条件判断”和“二进制位处理”两个场景切开讲顺着示例看会轻松很多。一、先问一句你在判断条件还是在处理二进制位、||、、|长得太像所以最容易被混在一起记。真正的分界不是“一个符号还是两个符号”而是你现在想做什么如果是在if、while里组合条件通常要的是短路逻辑、||。如果是在 boolean 表达式里强制两边都执行才会用非短路布尔运算、|、^。如果操作的是整数、标志位、掩码、哈希、权限位才是在做按位运算、|、^、~、、、。同一个符号在不同操作数类型下含义会变运算符操作数类型含义是否短路boolean短路逻辑与是左边为false时右边不执行||boolean短路逻辑或是左边为true时右边不执行boolean非短路逻辑与否两边都会执行|boolean非短路逻辑或否两边都会执行^boolean逻辑异或否两边都会执行整数类型按位与不属于短路逻辑|整数类型按位或不属于短路逻辑^整数类型按位异或不属于短路逻辑~整数类型按位取反不属于短路逻辑这里的“整数类型”包括byte、short、char、int、long。其中byte、short、char参与位运算时会先提升成int。二、和||短路的意义是“右边可能不执行”是短路逻辑与左边已经是false时整个表达式一定是false右边不会再算。示例代码Java短路与避免空指针Stringsnull;System.out.println(s!nulls.length()0);// false这段代码不会抛空指针异常因为s ! null已经是falses.length()根本不会执行。||是短路逻辑或左边已经是true时整个表达式一定是true右边不会再算。示例代码Java短路或跳过右侧判断intscore95;if(score90||score100){System.out.println(excellent);}这里score 90已经为true后面的score 100不需要再判断。短路不是语法小优化而是很多保护性写法成立的原因。常见写法示例代码Java常见保护性判断if(user!nulluser.isActive()){// 先防 null再访问对象方法}if(listnull||list.isEmpty()){// list 为 null 时不会继续调用 isEmpty()}判断条件时默认选择、||。这不是因为它们“更高级”而是它们更符合条件判断的预期前面的条件已经能决定结果时后面的条件就不应该再制造副作用或异常。三、和|放在 boolean 上能用但不短路、|不只属于位运算。它们也可以作用在 boolean 上示例代码Javaboolean 上的非短路运算booleanafalse;booleanbtrue;System.out.println(ab);// falseSystem.out.println(a|b);// true结果看起来和、||很像但执行过程不一样、|会把左右两边都算完。示例代码Java单个不会短路Stringsnull;System.out.println(s!nulls.length()0);这段代码会抛NullPointerException。虽然左边s ! null是false但单个不短路右边的s.length()仍然会执行。|也一样示例代码Java|会执行右侧方法staticbooleanlogAndReturnTrue(){System.out.println(right side executed);returntrue;}publicstaticvoidmain(String[]args){booleanlefttrue;System.out.println(left||logAndReturnTrue());// 右边不执行System.out.println(left|logAndReturnTrue());// 右边会执行}所以在普通条件判断里看到单个、|要先警惕它可能不是作者想要的短路逻辑。^放在 boolean 上表示逻辑异或左右刚好一个为true结果才是true。示例代码Javaboolean 异或System.out.println(true^false);// trueSystem.out.println(true^true);// false它也不会短路因为异或必须知道左右两边的值才能判断“是否不同”。四、、|、^、~放在整数上逐位计算位运算不是在比较“整个数真不真”而是在比较每一位二进制。1. 按位与对应位都为1结果位才是1。示例代码Java按位与System.out.println(35);// 1二进制过程text3 5 的逐位结果3 - 0011 5 - 0101 0001 - 1常见用途是检查某一位是否存在示例代码Java用掩码检查权限位intREAD1;// 0001intWRITE11;// 0010intpermissionREAD|WRITE;booleancanRead(permissionREAD)!0;注意括号不能省。!的优先级高于如果写成permission READ ! 0会先算READ ! 0表达式就变成int boolean直接编译失败。2. 按位或|对应位只要有一个是1结果位就是1。示例代码Java按位或System.out.println(6|2);// 6二进制过程text6 | 2 的逐位结果6 - 0110 2 - 0010 | 0110 - 6常见用途是合并标志位示例代码Java合并多个标志位intREAD1;// 0001intWRITE11;// 0010intEXEC12;// 0100intpermissionREAD|WRITE;// 同时拥有 READ 和 WRITEpermissionpermission|EXEC;3. 按位异或^对应位不同结果位才是1。示例代码Java按位异或System.out.println(5^9);// 12二进制过程text5 ^ 9 的逐位结果5 - 0101 9 - 1001 ^ 1100 - 12异或常见于“切换某一位”的场景同一位异或1会翻转异或0会保持不变。示例代码Java用异或切换某一位intflag0b0101;intmask0b0001;System.out.println(flag^mask);// 0b01004. 按位取反~~会把每一位都翻转0变11变0。示例代码Java按位取反System.out.println(~5);// -6这个结果看起来反直觉是因为 Java 的int使用 32 位二进制补码表示。对任意int x都有规律说明text按位取反和负数的关系~x -x - 1所以~5等于-6。五、移位运算移动的是二进制位移位运算只用于整数类型。运算符名称高位或低位如何补左移右侧补0有符号右移左侧补符号位正数补0负数补1无符号右移左侧一律补0左移常能看成乘以2的若干次方示例代码Java左移两位System.out.println(52);// 20二进制过程text左移后的位变化0000 0101 - 0001 0100右移要更谨慎。对非负数 n通常像除以2^n示例代码Java非负数右移System.out.println(152);// 3但对负数不要简单等同于/。Java 的整数除法向0截断而会保留符号位示例代码Java负数右移和整数除法的差异System.out.println(-5/2);// -2System.out.println(-51);// -3不保留符号位左侧永远补0。因此负数无符号右移后常会变成很大的正数示例代码Java有符号右移和无符号右移System.out.println(-63);// -1System.out.println(-63);// 536870911初学阶段不要为了“看起来更底层”而用移位替代乘除。只有在处理掩码、哈希、编码、底层协议、集合源码这类明确依赖二进制布局的场景里移位才是自然表达。六、优先级能加括号就别考验读者逻辑运算和位运算的优先级大致可以记成优先级速查text逻辑与位运算从高到低~、! // 一元运算优先级高 、、 // 移位 、、、 // 关系比较 、! // 相等比较 // 按位与 / 非短路逻辑与 ^ // 异或 | // 按位或 / 非短路逻辑或 // 短路逻辑与 || // 短路逻辑或这能解释一些表达式为什么能按预期运行示例代码Java不写括号时的表达式booleanresultxy!z;它等价于示例代码Java加括号后的等价表达式booleanresult(xy)(!z);但工程代码里不建议把优先级当成炫技空间。尤其是位运算和比较混在一起时括号会让语义清楚很多示例代码Java位运算和比较混用时加括号booleanhasRead(permissionREAD)!0;intcombinedREAD|WRITE|EXEC;intthirdBitvalue(12);判断规则很简单如果读者需要停下来回忆优先级表括号就应该出现。七、实战判断口诀遇到、||、、|、^、~、移位运算时可以按这几个问题判断是不是条件判断是优先使用、||。右边是否可能有空指针、数组越界、方法副作用是更要使用短路逻辑。操作数是不是整数而且你关心的是二进制的某一位是使用位运算。是不是要表示权限、状态、掩码、哈希扰动、编码解码是位运算可能合适。只是想把两个 boolean 条件连起来不要随手写单个、|。最容易记错的一句话是记忆口诀text一句话区分短路逻辑和位运算短路逻辑看“要不要继续算”位运算看“每一位怎么算”。、||解决的是控制流问题、|、^、~、、、解决的是二进制表示问题。把这个边界立住空指针保护、条件副作用、权限掩码和移位计算就不会混成一团。