【Java SE 运算符】全面解析与实践指南

文章目录

运算符是 Java 中实现数据计算、逻辑判断、赋值操作的核心语法元素,它基于基本数据类型(如 int、double、char 等)实现运算,按功能可分为 7 大类。掌握运算符的用法与特性,是编写正确、高效代码的基础,尤其需注意不同类型运算的转换规则与特殊场景(如溢出、短路逻辑)。

一、运算符分类总览

Java SE 的运算符按功能可划分为 7 大类,每类对应特定业务场景(如算术计算、条件判断),具体分类如下:

运算符类别 包含运算符 核心作用 操作数数量
算术运算符 +(加)、-(减)、*(乘)、/(除)、%(模)、++(自增)、--(自减) 数值计算 双目(++/-- 为单目)
赋值运算符 =(基本赋值)、+=(加后赋值)、-=(减后赋值)、*=(乘后赋值)等 变量赋值与简化运算 双目
比较运算符 ==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于) 判断两个值的关系 双目
逻辑运算符 &&(短路与)、 (短路或)、!(非)、&(逻辑与)、
位运算符 &(按位与)、 (按位或)、^(按位异或)、~(按位取反)、<<(左移)、>>(右移)、>>>(无符号右移) 二进制位级操作
条件运算符 ?:(三目运算符) 简化 if-else 判断的二选一赋值 三目
instanceof 运算符 instanceof 判断对象是否为指定类 / 接口实例 双目

二、单类运算符深度解析(含示例与原理)

(一)算术运算符:数值计算的核心工具

算术运算符用于整数、浮点数的计算,需注意整数除法截断模运算正负号自增 / 自减的前置与后置差异三大关键点。

1. 基本算术运算符(+、-、*、/、%)
  • 语法操作数1 运算符 操作数2(双目运算符,需两个操作数)

  • 功能与示例

运算符 功能 代码示例 结果 注意事项
+ 加法(含正号) int a = 5 + 3; double b = 2.5 + 1.5; a=8 b=4.0 若操作数含 char,会自动转 Unicode 值计算(如'A' + 1 = 66
- 减法(含负号) int c = 10 - 4; double d = 5.0 - 2.3; c=6 d=2.7 负号可作单目运算符(如int e = -3;,表示负数)
* 乘法 int f = 3 * 4; double g = 2.0 * 3.5; f=12 g=7.0 整数相乘可能溢出(如int h = 2147483647 * 2;,结果为负)
/ 除法 int i = 10 / 3; double j = 10.0 / 3; i=3 j≈3.333 整数除法仅保留整数部分(截断,非四舍五入);除数不能为 0
% 模运算(取余数) int k = 10 % 3; int l = -10 % 3; k=1 l=-1 结果符号与被除数 一致;浮点数也支持模运算(如5.5 % 2.0 = 1.5
  • 关键避坑点

    • 整数除法截断:7 / 2 = 3(非 3.5),若需小数结果,需将任一操作数转为浮点数(如7.0 / 2 = 3.5);

    • 除数不能为 0:整数除法除数为 0 会抛ArithmeticException(如5 / 0),浮点数除法除数为 0 会得到Infinity(如5.0 / 0 = Infinity)。

2. 自增 / 自减运算符(++、--)
  • 语法++变量(前置自增)、变量++(后置自增);--变量(前置自减)、变量--(后置自减)(单目运算符,仅需一个操作数)

  • 核心差异:前置先运算再赋值,后置先赋值再运算;

  • 代码示例与解析

    // 自增示例

    int x = 5;

    int y = ++x; // 前置自增:x先+1(x=6),再赋值给y → y=6

    int z = x++; // 后置自增:先将x=6赋值给z(z=6),再x+1(x=7)

    System.out.println(x); // 7

    System.out.println(y); // 6

    System.out.println(z); // 6

    // 自减示例

    int m = 3;

    int n = --m; // 前置自减:m先-1(m=2),再赋值给n → n=2

    int p = m--; // 后置自减:先将m=2赋值给p(p=2),再m-1(m=1)

    System.out.println(m); // 1

    System.out.println(n); // 2

    System.out.println(p); // 2

  • 注意事项

    • 自增 / 自减仅适用于变量(如++5报错,不能操作常量);

    • 避免在复杂表达式中使用(如int q = x++ + ++x,结果依赖编译器,可读性差)。

(二)赋值运算符:变量赋值与简化运算

赋值运算符的核心是=,其他均为 "运算 + 赋值" 的复合简化形式,可自动处理类型转换(如byte += int无需强制转换)。

1. 基本赋值运算符(=)
  • 语法变量 = 表达式

  • 功能:将右侧表达式结果赋值给左侧变量(左侧必须是可修改的变量,不能是常量或表达式);

  • 代码示例

    int a = 10; // 直接赋值常量

    double b = 3.14; // 赋值浮点数

    int c = a + 5; // 赋值表达式结果(a+5=15 → c=15)

    // 错误示例:左侧不能是常量或表达式

    // 10 = a; // 报错:左侧必须是变量

    // a + b = 20; // 报错:左侧必须是变量

2. 复合赋值运算符(+=、-=、*=、/=、%= 等)
  • 语法变量 复合运算符 表达式 → 等价于 变量 = (变量类型) (变量 运算符 表达式)(自动隐含强制类型转换);

  • 功能与示例

运算符 等价写法 代码示例 结果 隐含转换说明
+= 变量 = 变量 + 表达式 byte x = 5; x += 3;(等价 x=(byte)(x+3)) x=8 若表达式是 int(如 3),自动转 byte(避免x = x + 3的编译错误)
-= 变量 = 变量 - 表达式 int y = 10; y -= 4; y=6 无类型转换问题(同类型运算)
*= 变量 = 变量 * 表达式 double z = 2.5; z *= 2; z=5.0 浮点数运算保留小数
/= 变量 = 变量 / 表达式 int m = 10; m /= 3; m=3 整数除法截断
%= 变量 = 变量 % 表达式 int n = 10; n %= 3; n=1 结果符号与被除数一致
  • 关键优势 :复合赋值运算符可避免 "类型不匹配" 的编译错误(如byteint运算),无需手动强制转换。

(三)比较运算符:判断关系的逻辑基础

比较运算符用于判断两个值的大小或相等关系,结果仅为 boolean 类型(true/false),常用于 if 条件、while 循环的判断条件。

1. 所有比较运算符详解
  • 语法操作数1 运算符 操作数2(双目运算符)

  • 功能与示例(基于 int、double、String 的比较):

    // 1. 数值比较(int/double)

    int a = 5, b = 3;

    double c = 2.5, d = 2.5;

    System.out.println(a > b); // true(5>3)

    System.out.println(a < b); // false(5<3)

    System.out.println(a >= 5); // true(5>=5)

    System.out.println(b <= 2); // false(3<=2)

    System.out.println(c == d); // true(2.5==2.5)

    System.out.println(c != d); // false(2.5!=2.5)

    // 2. 字符串比较(注意:String是引用类型,==比较地址,equals()比较内容)

    String s1 = "abc";

    String s2 = new String("abc");

    System.out.println(s1 == s2); // false(s1和s2地址不同)

    System.out.println(s1.equals(s2)); // true(s1和s2内容相同)

  • 关键避坑点

    • 引用类型(如 String、自定义类)的==比较 "内存地址",而非内容;比较内容需用equals()方法(如 String 的equals());

    • 浮点数比较避免直接用==:因精度问题(如0.1 + 0.2 = 0.30000000000000004),需用 "差值绝对值小于极小值" 判断(如Math.abs(0.1+0.2 - 0.3) < 1e-9)。

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

逻辑运算符用于连接多个 boolean 表达式(或单个 boolean 值),核心分为短路逻辑(&&、||)非短路逻辑(&、|),差异在于 "是否提前终止运算"。

1. 逻辑运算符分类与示例
  • 语法布尔表达式1 逻辑运算符 布尔表达式2!!布尔表达式

  • 功能对比与代码示例

运算符 类型 功能(布尔值 a、b) 短路特性 代码示例(a=true, b=false) 结果
&& 短路与 a 且 b:均为 true 则 true,否则 false 左假则右不执行 (a == true) && (++b == true) true
短路或 a 或 b:任一为 true 则 true,否则 false 左真则右不执行
& 非短路与 同 &&,但无论左值如何,右值必执行 (a == true) & (++b == true) true
非短路或 ,但无论左值如何,右值必执行
! 非(取反) 真变假,假变真 - !(a == true) false
^ 异或 a 和 b 不同则 true,相同则 false (a == true) ^ (b == true) true
  • 核心应用场景

    • 短路逻辑(&&、||):用于 "无需执行所有表达式" 的场景(如判断 "用户不为 null 且用户名正确":user != null && user.getName().equals("admin"),避免user为null时调用getName()抛空指针异常);

    • 非短路逻辑(&、|):用于 "必须执行所有表达式" 的场景(如同时判断两个条件并记录日志,右表达式为日志打印代码)。

(五)位运算符:二进制位的高效操作

位运算符直接操作整数的二进制位(如 byte、short、int、long),运算效率极高,常用于状态标记数值压缩高性能计算场景(如网络协议、底层开发)。

1. 位运算符分类与原理

整数在内存中以 "补码" 形式存储,位运算直接操作补码的每一位(0 表示 false,1 表示 true),具体运算符如下:

运算符 类型 功能(二进制位 a、b) 代码示例(int a=6→0110, b=3→0011) 结果(二进制→十进制)
& 按位与 a&b:同 1 则 1,否则 0 a & b 0010 → 2
按位或 a b:同 0 则 0,否则 1
^ 按位异或 a^b:不同则 1,相同则 0 a ^ b 0101 → 5
~ 按位取反 ~a:0 变 1,1 变 0(含符号位) ~a 11111111111111111111111111111001 → -7
<< 左移 a<<n:a 的二进制左移 n 位,右补 0 a << 2 011000 → 24
>> 右移 a>>n:a 的二进制右移 n 位,左补符号位 a >> 2 0001 → 1
>>> 无符号右移 a>>>n:a 的二进制右移 n 位,左补 0 a >>> 2 0001 → 1
  • 关键解析

    • 按位取反(~):int 是 32 位,取反后符号位变 1(负数),结果为 "-(原数 + 1)"(如~6 = -7);

    • 左移(<<):等价于 "a × 2^n"(如6<<2 = 6×4=24),无符号扩展;

    • 右移(>>):正数左补 0,负数左补 1(如-6>>2 = -2);无符号右移(>>>):无论正负左补 0(如-6>>>2 = 1073741822)。

2. 典型应用场景:状态标记

用一个 int 的不同二进制位表示多个状态(如 "用户权限":位 0 表示 "读",位 1 表示 "写",位 2 表示 "删"),通过位运算高效判断 / 修改状态:

复制代码
// 定义状态位(每个状态占1位)

int READ = 1 << 0;  // 0001(读权限)

int WRITE = 1 << 1; // 0010(写权限)

int DELETE = 1 << 2;// 0100(删权限)

// 给用户分配权限(按位或 |:添加权限)

int userPerm = READ | WRITE; // 0011(有读、写权限)

// 判断用户是否有某权限(按位与 &:结果非0则有)

boolean hasRead = (userPerm & READ) != 0;    // true(有读权限)

boolean hasDelete = (userPerm & DELETE) != 0;// false(无删权限)

// 给用户添加删权限(按位或 |)

userPerm = userPerm | DELETE; // 0111(读、写、删权限)

// 给用户移除写权限(按位异或 ^:移除已有的位)

userPerm = userPerm ^ WRITE; // 0101(读、删权限)

(六)条件运算符(?:):简化 if-else 的三目工具

条件运算符是 Java 中唯一的三目运算符,用于 "根据条件二选一赋值",可简化简单的 if-else 逻辑,提高代码简洁性。

1. 语法与功能
  • 语法条件表达式 ? 表达式1 : 表达式2

  • 逻辑 :若条件表达式为true,执行表达式 1 并返回结果;否则执行表达式 2 并返回结果;

  • 核心要求 :表达式 1 与表达式 2 的返回值类型必须兼容(可自动转换或相同类型);

  • 代码示例

    // 场景1:判断两个数的最大值

    int a = 5, b = 8;

    int max = (a > b) ? a : b; // 条件为false,返回b → max=8

    // 场景2:判断学生成绩是否及格

    int score = 75;

    String result = (score >= 60) ? "及格" : "不及格"; // 条件为true,返回"及格"

    // 场景3:类型兼容(int自动转double)

    double num = (a > b) ? 10 : 3.5; // 表达式1(10)转double → num=3.5

  • 注意事项

    • 避免嵌套过深(如a>b ? (a>c ? a:c) : (b>c ? b:c)),可读性差,复杂逻辑建议用 if-else;

    • 表达式 1 与表达式 2 不能是 void 类型(必须有返回值,如(a>b) ? System.out.println(a) : System.out.println(b)报错)。

(七)instanceof 运算符:对象类型的判断工具

instanceof 用于判断 "对象是否为指定类的实例" 或 "对象是否实现指定接口",返回 boolean 类型,常用于多态场景中的类型判断(如向下转型前的安全检查)。

1. 语法与功能
  • 语法对象 instanceof 类/接口

  • 核心规则

    • 若对象为null,结果恒为false

    • 若对象是指定类的实例(包括子类实例),或实现指定接口,结果为true

  • 代码示例

    // 定义父类、子类与接口

    class Animal {}

    class Dog extends Animal implements Runnable {}

    interface Runnable {}

    // 创建对象

    Animal animal = new Dog();

    Dog dog = new Dog();

    Runnable runnable = new Dog();

    // instanceof判断

    System.out.println(animal instanceof Animal); // true(animal是Animal实例)

    System.out.println(animal instanceof Dog); // true(animal是Dog实例,Dog是Animal子类)

    System.out.println(animal instanceof Runnable); // true(animal是Runnable实现类实例)

    System.out.println(dog instanceof Animal); // true(Dog是Animal子类)

    System.out.println(runnable instanceof Dog); // true(runnable是Dog实例)

    System.out.println(null instanceof Animal); // false(null无类型)

  • 应用场景 :向下转型前的安全检查(避免ClassCastException):

    Animal a = new Dog();

    // 安全转型:先判断是否为Dog实例

    if (a instanceof Dog) {

    Dog d = (Dog) a; // 向下转型,安全无异常

    }

三、运算优先级与结合性:解决表达式运算顺序问题

当一个表达式包含多个运算符时,优先级高的运算符先执行 ;若优先级相同,按结合性 (从左到右或从右到左)执行。无需死记优先级,复杂表达式建议用括号 () 明确顺序(可读性更高)。

1. 运算符优先级排序(从高到低,关键类别)

优先级 运算符类别 具体运算符(示例) 结合性
1 括号 () 从左到右
2 单目运算符 ++、--、!、~、+(正号)、-(负号) 从右到左
3 算术运算符 *、/、% 从左到右
4 算术运算符 +、- 从左到右
5 位运算符 <<、>>、>>> 从左到右
6 比较运算符 >、<、>=、<= 从左到右
7 比较运算符 ==、!= 从左到右
8 位运算符 & 从左到右
9 位运算符 ^ 从左到右
10 位运算符
11 逻辑运算符 && 从左到右
12 逻辑运算符
13 条件运算符 ?: 从右到左
14 赋值运算符 =、+=、-=、*= 等 从右到左

2. 优先级与结合性示例解析

复制代码
// 示例1:算术运算符优先级(\*、/高于+、-)

int a = 3 + 4 \* 2; // 先算4\*2=8,再算3+8=11 → a=11

int b = (3 + 4) \* 2; // 括号优先级最高,先算3+4=7,再算7\*2=14 → b=14

// 示例2:赋值运算符结合性(从右到左)

int c = d = 5; // 先算d=5,再算c=d → c=5, d=5

// 示例3:单目运算符与算术运算符(单目高于算术)

int e = -3 + 5; // 先算-3(单目负号),再算-3+5=2 → e=2

// 示例4:逻辑运算符优先级(&&高于||)

boolean f = true || false && false; // 先算false&\&false=false,再算true||false=true → f=true

四、实践避坑指南(开发中高频错误)

  1. 整数溢出问题

    整数运算(如 int 的最大值 + 1)会溢出且无报错,需用long接收结果或手动判断(如if (a > Integer.MAX_VALUE - b) { 抛出溢出异常 });

  2. 浮点数比较用 ==

    因精度问题(如0.1+0.2≠0.3),需用Math.abs(结果-预期值) < 1e-9判断;

  3. String 用 == 比较内容

    String 是引用类型,==比较地址,比较内容必须用equals()(空指针安全写法:"abc".equals(s),避免s.equals("abc"));

  4. 短路逻辑的空指针风险

    若左表达式为 false(&&)或 true(||),右表达式不执行,需确保左表达式能过滤无效场景(如user != null && user.getName().equals("admin"),避免 user 为 null 时调用 getName ());

  5. 自增 / 自减在复杂表达式中滥用

    int x = 5; int y = x++ + ++x;(结果依赖编译器),建议拆分为多行代码(可读性更高,避免歧义);

  6. 位运算用于浮点数

    位运算符仅支持整数类型(byte、short、int、long),浮点数需先转整数(如(int)3.5 & 1),否则编译报错。

五、总结:运算符的选择与使用原则

  1. 优先用短路逻辑(&&、||):减少无效运算,避免空指针异常(如判断对象非 null 后再调用方法);

  2. 复杂表达式用括号:无需依赖优先级,括号能明确运算顺序,提高代码可读性;

  3. 位运算用于高性能场景:如状态标记、数值压缩(比普通 if-else 效率更高);

  4. 条件运算符简化简单判断:仅用于 "二选一赋值" 场景,复杂逻辑用 if-else(避免嵌套);

  5. 类型转换需显式 :除复合赋值运算符的隐含转换外,不同类型运算需手动强制转换(如int a = (int)3.5),避免编译错误。

掌握 Java SE 运算符,需结合基本数据类型的特性(如 int 的范围、double 的精度),通过大量实践理解不同场景的正确用法,才能避免常见错误,编写高效、健壮的代码。

相关推荐
侠客行031721 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪21 小时前
深入浅出LangChain4J
java·langchain·llm
老毛肚1 天前
MyBatis体系结构与工作原理 上篇
java·mybatis
风流倜傥唐伯虎1 天前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
Yvonne爱编码1 天前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚1 天前
JAVA进阶之路——无奖问答挑战1
java·开发语言
你这个代码我看不懂1 天前
@ConditionalOnProperty不直接使用松绑定规则
java·开发语言
fuquxiaoguang1 天前
深入浅出:使用MDC构建SpringBoot全链路请求追踪系统
java·spring boot·后端·调用链分析
琹箐1 天前
最大堆和最小堆 实现思路
java·开发语言·算法
__WanG1 天前
JavaTuples 库分析
java