Java 运算符全解析:从基础用法到优先级避坑,一文吃透 5 大类运算符

在 Java 开发中,运算符是构建代码逻辑的 "基本零件"------ 无论是简单的数值计算,还是复杂的条件判断、位操作,都离不开运算符的灵活运用。但很多开发者在实际开发中常踩 "整数除法丢精度"" 逻辑短路漏执行 ""优先级混淆算错值" 等坑。本文将系统拆解算术、赋值、比较、逻辑、位 5 大类运算符,结合实战代码与优先级可视化图,帮你从 "会用" 到 "用对"。

​编辑

一、算术运算符:数值计算的核心(7 种)

算术运算符用于整数、浮点数的加减乘除等计算,其中整数除法取模是高频坑点。

1. 基础用法与代码示例

运算符 名称 作用 示例(a=10, b=3) 结果
+ 加法 数值相加 / 字符串拼接 a+b / "a"+b 13 / "103"
- 减法 数值相减 a-b 7
* 乘法 数值相乘 a*b 30
/ 除法 数值相除(整数取整) a/b / 10.0/3 3 / 3.333...
% 取模(余) 求被除数除以除数的余数 a%b / -10%3 1 / 2
++ 自增 数值 + 1(前置先加后用,后置先用后加) ++a / a++ 11 / 10
-- 自减 数值 - 1(同自增规则) --a / a-- 9 / 10
csharp 复制代码
public class ArithmeticDemo {
    public static void main(String[] args) {
        // 1. 整数除法坑点:结果自动取整,不会四舍五入
        int num1 = 10;
        int num2 = 3;
        System.out.println("整数除法:" + num1 / num2); // 输出3(而非3.333)
        System.out.println("浮点数除法:" + (double)num1 / num2); // 输出3.3333333333333335

        // 2. 取模正负性:结果符号与被除数一致
        System.out.println("正被除数取模:" + 10 % 3); // 1
        System.out.println("负被除数取模:" + (-10) % 3); // -1(重点:不是2)

        // 3. 自增自减的前置/后置差异
        int a = 5;
        int b = ++a; // 先加后用:a=6,b=6
        int c = a--; // 先用后减:c=6,a=5
        System.out.println("a=" + a + ", b=" + b + ", c=" + c); // a=5, b=6, c=6

        // 4. 字符串拼接优先级(+遇字符串则拼接)
        System.out.println("字符串拼接1:" + 10 + 3); // "103"
        System.out.println("字符串拼接2:" + (10 + 3)); // "13"
    }
}

2. 避坑指南

  • 整数除法必须先转浮点数:若需精确结果,至少将一个操作数转为doublefloat
  • 取模别忽略符号:判断奇偶性时用num % 2 == 0(负数也适用),避免依赖正余数;
  • 自增自减别嵌套:a++ + ++a这类表达式可读性差且易算错,建议拆分为多行。

二、赋值运算符:变量赋值的简化技巧(12 种)

赋值运算符用于将右侧值赋给左侧变量,复合赋值运算符(+=、-= 等)是简化代码的核心,且隐含 "自动类型转换" 特性。

1. 基础用法与代码示例

运算符 名称 作用 等效表达式
= 基本赋值 将右侧值赋给左侧变量 a = b
+= 加后赋值 左侧 + 右侧后赋给左侧 a = (类型) a + b
-= 减后赋值 左侧 - 右侧后赋给左侧 a = (类型) a - b
*= 乘后赋值 左侧 * 右侧后赋给左侧 a = (类型) a * b
/= 除后赋值 左侧 / 右侧后赋给左侧 a = (类型) a /b
%= 模后赋值 左侧 % 右侧后赋给左侧 a = (类型) a % b
&= 与后赋值 左侧 & 右侧后赋给左侧 a = a & b
= 或后赋值 左侧 右侧后赋给左侧 a = a b
^= 异或后赋值 左侧 ^ 右侧后赋给左侧 a = a ^ b
>>= 右移后赋值 左侧 >> 右侧后赋给左侧 a = a >> b
<<= 左移后赋值 左侧 << 右侧后赋给左侧 a = a << b
>>>= 无符号右移赋值 左侧 >>> 右侧后赋给左侧 a = a >>> b
csharp 复制代码
public class AssignmentDemo {
    public static void main(String[] args) {
        // 1. 复合赋值的隐含类型转换(重点坑点)
        byte num = 10;
        // num = num + 5; // 报错:int不能转byte
        num += 5; // 正常执行:等效于 num = (byte)(num + 5),结果15

        // 2. 赋值运算符的右结合性(从右向左计算)
        int a, b, c;
        a = b = c = 20; // 先c=20,再b=20,最后a=20
        System.out.println("a=" + a + ", b=" + b + ", c=" + c); // 20,20,20

        // 3. 位运算赋值的简化(后续位运算符详解)
        int flag = 1; // 二进制 0001
        flag |= 2; // 0001 | 0010 = 0011(3)
        System.out.println("位或赋值后:" + flag); // 3
    }
}

2. 避坑指南

  • 复合赋值自动转类型:对byteshortchar等小类型,+=会自动强转,避免直接赋值的编译错误;
  • 别混淆 "=" 和 "==":赋值是 "=",比较相等是 "==",写条件判断时极易手抖写错。

三、比较运算符:条件判断的依据(6 种)

比较运算符用于判断两个值的关系,结果始终是 boolean 类型(true/false),常与 if、while 等流程控制结合使用。

1. 基础用法与代码示例

运算符 名称 作用 示例(a=10, b=3) 结果
== 等于 判断两个值是否相等 a==b / 10==10.0 false / true
!= 不等于 判断两个值是否不相等 a!=b true
大于 判断左侧是否大于右侧 a>b true
< 小于 判断左侧是否小于右侧 a<b false
>= 大于等于 判断左侧是否大于等于右侧 a>=b true
<= 小于等于 判断左侧是否小于等于右侧 a<=b false
csharp 复制代码
public class ComparisonDemo {
    public static void main(String[] args) {
        // 1. 基本类型 vs 引用类型的"=="差异
        int num1 = 10;
        int num2 = 10;
        System.out.println("基本类型==:" + (num1 == num2)); // true(值相等)

        String str1 = new String("java");
        String str2 = new String("java");
        System.out.println("引用类型==:" + (str1 == str2)); // false(地址不同)
        System.out.println("引用类型equals:" + str1.equals(str2)); // true(内容相等)

        // 2. 浮点数比较的坑(避免直接用==)
        double d1 = 0.1;
        double d2 = 0.2;
        double sum = d1 + d2;
        System.out.println("0.1+0.2==0.3?" + (sum == 0.3)); // false(精度丢失)
        // 正确写法:判断差值小于极小值
        System.out.println("浮点数比较正确写法:" + (Math.abs(sum - 0.3) < 1e-9)); // true
    }
}

2. 避坑指南

  • 引用类型别用 "==" 比内容:==比较引用地址,内容比较用equals(注意 null 判断,避免空指针);
  • 浮点数禁止直接 "==":由于二进制存储精度问题,需通过Math.abs(差值) < 1e-9判断相等;
  • 比较表达式不能连写:1 < x < 3在 Java 中非法(会先算 1<x 得到 boolean,再用 boolean 和 3 比较),需拆分为x>1 && x<3

四、逻辑运算符:布尔值的组合判断(6 种)

逻辑运算符用于连接多个 boolean 表达式,核心是短路特性(影响代码执行顺序),分为 "短路型" 和 "非短路型"。

1. 基础用法与代码示例

运算符 名称 作用(左右为 boolean 表达式) 短路特性 示例(a=true, b=false) 结果
&& 逻辑与 左右都为 true 则 true 短路(左 false 则不执行右) a&&b / b&&(1/0==0) false /false(不报错)
逻辑或 左右有一个 true 则 true 短路(左 true 则不执行右) a b / a (1/0==0) true /true(不报错)
! 逻辑非 取反(单目运算符) !a false
& 逻辑与(非短路) 左右都为 true 则 true 非短路(必执行右) a&b / b&(1/0==0) false / 报错(执行了 1/0)
逻辑或(非短路) 左右有一个 true 则 true 非短路(必执行右) a b / a (1/0==0) true / 报错(执行了 1/0)
逻辑异或 左右不同则 true,相同则 false a^b / a^a true / false
arduino 复制代码
public class LogicDemo {
    public static void main(String[] args) {
        // 1. 短路特性的实际影响(性能+执行顺序)
        int num = 10;
        boolean result1 = (num > 20) && (num++ > 5); // 左false,右不执行
        System.out.println("短路与后num:" + num); // 10(num++未执行)

        boolean result2 = (num < 20) || (num++ > 5); // 左true,右不执行
        System.out.println("短路或后num:" + num); // 10(num++未执行)

        // 2. 非短路与的坑(即使左false,右仍执行)
        boolean result3 = (num > 20) & (num++ > 5);
        System.out.println("非短路与后num:" + num); // 11(num++执行了)

        // 3. 逻辑非的优先级(高于算术/比较运算符)
        boolean flag = !(10 > 5);
        System.out.println("逻辑非结果:" + flag); // false
    }
}

2. 避坑指南

  • 优先用短路运算符:&&||可避免无效计算(如右侧有耗时操作或可能报错的代码);
  • 非短路仅用特殊场景:需强制执行右侧代码时(如同时判断条件 + 更新状态)才用&/|
  • 加括号明确优先级:逻辑运算符优先级低(低于比较运算符),复杂表达式必须加括号,如(a>b) && (c<d)

五、位运算符:二进制级别的高效操作(7 种)

位运算符直接操作整数的二进制位,执行效率极高,常用于权限控制、数据压缩等场景,但上手难度较高。

1. 基础概念:二进制位的表示

Java 中整数以补码形式存储,以int(32 位)为例:

  • 正数:原码 = 反码 = 补码(如 10 的二进制:00000000 00000000 00000000 00001010);
  • 负数:反码 = 原码除符号位外取反,补码 = 反码 + 1(如 - 10 的补码:11111111 11111111 11111111 11110110)。

2. 基础用法与代码示例

运算符 名称 作用(操作二进制位) 示例(a=10=00001010, b=3=00000011) 结果(二进制→十进制)
& 位与 同位都为 1 则 1,否则 0 a&b = 00000010 2
位或 同位有 1 则 1,否则 0 a b = 00001011 11
位异或 同位不同则 1,相同则 0 a^b = 00001001 9
~ 位非 所有位取反(单目运算符) ~a = 11110101(补码) -11
<< 左移 整体左移 n 位,右补 0 a<<2 = 00101000 40(10*2²)
>> 算术右移 整体右移 n 位,左补符号位 a>>2 = 00000010(正数) 2(10/2²)
>>> 无符号右移 整体右移 n 位,左补 0(忽略符号) (-10)>>>28 = 00001111 15
csharp 复制代码
public class BitDemo {
    public static void main(String[] args) {
        // 1. 位运算的经典场景:权限控制(每一位代表一个权限)
        int READ = 1 << 0; // 0001(读权限)
        int WRITE = 1 << 1; // 0010(写权限)
        int DELETE = 1 << 2; // 0100(删权限)

        int userPerm = READ | WRITE; // 0011(拥有读+写权限)
        // 判断是否有写权限
        boolean hasWrite = (userPerm & WRITE) != 0;
        System.out.println("是否有写权限:" + hasWrite); // true

        // 增加删权限
        userPerm |= DELETE; // 0111
        // 取消读权限
        userPerm &= ~READ; // 0110
        System.out.println("更新后权限(十进制):" + userPerm); // 6(0110)

        // 2. 左移/右移的高效计算(替代乘除2的n次方)
        int num = 10;
        System.out.println("左移2位(×4):" + (num << 2)); // 40
        System.out.println("算术右移2位(÷4):" + (num >> 2)); // 2

        // 3. 位异或的特性:a^a=0,a^0=a(交换两个数)
        int x = 5, y = 3;
        x = x ^ y; // x=6(110)
        y = x ^ y; // y=5(101)
        x = x ^ y; // x=3(011)
        System.out.println("交换后x=" + x + ", y=" + y); // 3,5
    }
}

3. 避坑指南

  • 移位别超范围:int左移超过 31 位、long超过 63 位会取模(如a<<33等效于a<<1);
  • 负数移位注意符号:算术右移(>>)会补符号位,无符号右移(>>>)会补 0,负数用 >>> 可能得到大正数;
  • 位运算仅适用于整数:浮点数不能用位运算符,编译会报错。

六、运算符优先级:避免 "算错值" 的核心规则

运算符优先级决定了表达式的计算顺序,优先级高的先执行;若优先级相同,则按 "结合性"(左结合 / 右结合)计算。记不住优先级?加括号就对了!

1. 优先级总表(从高到低,重点标红)

优先级 运算符组 运算符 结合性
1 括号 ()、[]、. 左结合
2 单目运算符 ++、--、~、!、(类型) 右结合
3 算术运算符(乘除) *、/、% 左结合
4 算术运算符(加减) +、- 左结合
5 移位运算符 <<、>>、>>> 左结合
6 比较运算符 >、<、>=、<= 左结合
7 相等运算符 ==、!= 左结合
8 位与 & 左结合
9 位异或 & 左结合
10 位或 左结合
11 逻辑与 && 左结合
12 逻辑或 左结合
13 三目运算符 条件?表达式 1: 表达式 2 右结合
14 赋值运算符 =、+=、-=、*=、/=、%= 等 右结合

2. 易错优先级示例解析

csharp 复制代码
public class PriorityDemo {
    public static void main(String[] args) {
        // 示例1:算术 vs 比较 vs 逻辑
        boolean res1 = 10 + 5 > 12 && 3 < 5; 
        // 执行顺序:(10+5) >12 → 15>12=true;true && (3<5) → true
        System.out.println("res1=" + res1); // true

        // 示例2:自增 vs 加法(单目优先级高于算术)
        int a = 2;
        int res2 = a++ + ++a; 
        // 执行顺序:a++(先用a=2,后a=3);++a(先a=4,后用4);2+4=6
        System.out.println("res2=" + res2); // 6

        // 示例3:赋值 vs 三目(三目优先级高于赋值)
        int b = 3, c = 5;
        int res3 = b > c ? b : c; 
        // 执行顺序:(b>c)→false;取c=5;赋值给res3
        System.out.println("res3=" + res3); // 5

        // 反例:不加括号的坑
        int res4 = 10 > 5 ? 2 + 3 : 4 + 5; 
        // 正确:(10>5)→true;(2+3)=5 → res4=5
        int res5 = 10 > 5 ? 2 + 3 : 4 * 5; 
        // 正确:(4*5)优先级高于三目?不!三目优先级13>赋值14,但算术3>三目13
        // 执行顺序:(10>5)→true;(2+3)=5;res5=5(若加括号更清晰)
    }
}

七、总结:从 "会用" 到 "用对" 的 3 个核心原则

  1. 优先加括号:即使记准优先级,复杂表达式加括号也能提升可读性,避免团队协作中的误解;
  2. 关注 "坑点细节" :整数除法转浮点数、浮点数不直接 ==、引用类型用 equals、逻辑短路影响执行顺序,这些是面试和开发中的高频错题;
  3. 位运算用在刀刃上:位运算效率高,但可读性差,仅在权限控制、性能敏感场景使用,普通计算优先用算术运算符。

运算符是 Java 的基础,但基础不牢则上层建筑不稳。掌握本文的用法、坑点和优先级规则,能帮你避免 80% 的运算符相关 bug,让代码更高效、更健壮。

相关推荐
xuejianxinokok2 小时前
透明的多级并发(行) 方式
后端
235162 小时前
【Redis】缓存击穿、缓存穿透、缓存雪崩的解决方案
java·数据库·redis·分布式·后端·缓存·中间件
Java水解3 小时前
深入掌握 ExcelJS:Node.js 中强大的 Excel 操作库
后端·excel
Java水解3 小时前
深度解析 Spring MVC `@ModelAttribute` 注解
后端·spring
调试人生的显微镜3 小时前
Python 爬虫 HTTPS 实战,requests httpx aiohttp 抓取技巧、证书问题与抓包调试全流程
后端
程序猿DD3 小时前
Spring Boot 4 与 Spring Framework 7 全面解析:新特性、升级要点与实战指南
java·spring boot·后端
用户6120414922134 小时前
jsp+servlet做的咖啡品牌管理后台
java·前端·后端
汇匠源4 小时前
基于springboot家政、上门服务、Java源码系统功能结构
java·spring boot·后端