第8章 Java运算符

掌握算术、关系、逻辑、赋值运算符的使用方法和优先级

学习目标

运算符概述

运算符是Java语言的基础组成部分,用于对变量和值执行操作。Java提供了丰富的运算符,包括算术运算符、关系运算符、逻辑运算符、赋值运算符、位运算符等。理解和掌握这些运算符的使用方法和优先级,是编写高质量Java程序的基础。

算术运算符

用于执行基本的数学运算,如加法、减法、乘法、除法等。

包括: +, -, *, /, %, ++, --

关系运算符

用于比较两个值的关系,返回布尔值。

包括: ==, !=, >, <, >=, <=

逻辑运算符

用于组合多个布尔表达式,支持短路求值。

包括: &&, ||, !

赋值运算符

用于给变量赋值,包括简单赋值和复合赋值。

包括: =, +=, -=, *=, /=, %=

位运算符

用于对整数的二进制位进行操作。

包括: &, |, ^, ~, <<, >>, >>>

其他运算符

包括三元运算符、类型检查运算符等。

包括: ?:, instanceof

算术运算符详解

基本算术运算符

运算符 名称 示例 结果 说明
+ 加法 5 + 3 8 两个操作数相加
- 减法 5 - 3 2 第一个操作数减去第二个操作数
* 乘法 5 * 3 15 两个操作数相乘
/ 除法 5 / 3 1 整数除法,舍去小数部分
% 取模 5 % 3 2 返回除法的余数

自增自减运算符

重要区别:

  • 前置自增/自减++a, --a):先改变值,再使用
  • 后置自增/自减a++, a--):先使用值,再改变
ArithmeticOperatorExample.java
public class ArithmeticOperatorExample {
    public static void main(String[] args) {
        // 基本算术运算
        int a = 10, b = 3;
        System.out.println("a + b = " + (a + b));  // 13
        System.out.println("a - b = " + (a - b));  // 7
        System.out.println("a * b = " + (a * b));  // 30
        System.out.println("a / b = " + (a / b));  // 3 (整数除法)
        System.out.println("a % b = " + (a % b));  // 1
        
        // 浮点除法
        double x = 10.0, y = 3.0;
        System.out.println("x / y = " + (x / y));  // 3.3333333333333335
        
        // 自增自减演示
        int count = 5;
        System.out.println("初始值: " + count);     // 5
        System.out.println("++count: " + (++count)); // 6 (先自增)
        System.out.println("count++: " + (count++)); // 6 (后自增)
        System.out.println("最终值: " + count);     // 7
    }
}
💻 查看完整代码 - 在线IDE体验

关系运算符详解

关系运算符用于比较两个值的关系,返回布尔值(truefalse)。

运算符 名称 示例 说明
== 等于 a == b 判断a和b是否相等
!= 不等于 a != b 判断a和b是否不相等
> 大于 a > b 判断a是否大于b
< 小于 a < b 判断a是否小于b
>= 大于等于 a >= b 判断a是否大于等于b
<= 小于等于 a <= b 判断a是否小于等于b

字符串比较注意事项:

  • == 比较的是引用(内存地址),不是内容
  • 使用 equals() 方法比较字符串内容
  • 使用 compareTo() 方法进行字符串大小比较
字符串比较示例
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");

// 引用比较
System.out.println(str1 == str2);        // true (字符串池)
System.out.println(str1 == str3);        // false (不同对象)

// 内容比较
System.out.println(str1.equals(str2));   // true
System.out.println(str1.equals(str3));   // true

逻辑运算符详解

逻辑运算符用于组合多个布尔表达式,常用于条件判断和流程控制。

运算符 名称 示例 说明
&& 逻辑与 a && b 当a和b都为true时返回true
|| 逻辑或 a || b 当a或b为true时返回true
! 逻辑非 !a 返回a的相反值

短路求值

短路求值机制:

  • 逻辑与(&&):如果左操作数为false,右操作数不会被计算
  • 逻辑或(||):如果左操作数为true,右操作数不会被计算

这种机制可以提高程序性能,避免不必要的计算。

短路求值示例
public class ShortCircuitExample {
    public static void main(String[] args) {
        // 短路与演示
        boolean result1 = false && expensiveOperation();
        // expensiveOperation() 不会被调用
        
        // 短路或演示
        boolean result2 = true || expensiveOperation();
        // expensiveOperation() 不会被调用
        
        // 实际应用:避免空指针异常
        String str = null;
        if (str != null && str.length() > 0) {
            System.out.println("字符串不为空");
        }
    }
    
    static boolean expensiveOperation() {
        System.out.println("执行昂贵的操作");
        return true;
    }
}

赋值运算符详解

赋值运算符用于给变量赋值,Java提供了简单赋值和复合赋值两种形式。

运算符 名称 示例 等价形式
= 简单赋值 a = b -
+= 加法赋值 a += b a = a + b
-= 减法赋值 a -= b a = a - b
*= 乘法赋值 a *= b a = a * b
/= 除法赋值 a /= b a = a / b
%= 取模赋值 a %= b a = a % b
赋值运算符示例
public class AssignmentExample {
    public static void main(String[] args) {
        int a = 10;
        System.out.println("初始值: a = " + a);  // 10
        
        a += 5;  // 等价于 a = a + 5
        System.out.println("a += 5: " + a);     // 15
        
        a *= 2;  // 等价于 a = a * 2
        System.out.println("a *= 2: " + a);     // 30
        
        a /= 3;  // 等价于 a = a / 3
        System.out.println("a /= 3: " + a);     // 10
        
        // 字符串连接赋值
        String message = "Hello";
        message += " World";  // 等价于 message = message + " World"
        System.out.println(message);          // "Hello World"
    }
}

运算符优先级

运算符优先级决定了表达式中运算符的执行顺序。优先级高的运算符先执行,优先级相同的运算符按结合性执行。

运算符优先级表(从高到低)

1
后缀运算符: expr++, expr--
2
一元运算符: ++expr, --expr, +expr, -expr, ~, !
3
乘除取模: *, /, %
4
加减: +, -
5
移位: <<, >>, >>>
6
关系: <, >, <=, >=, instanceof
7
相等: ==, !=
8
按位与: &
9
按位异或: ^
10
按位或: |
11
逻辑与: &&
12
逻辑或: ||
13
三元: ? :
14
赋值: =, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=, >>>=

最佳实践:

  • 使用括号明确表达式的计算顺序,提高代码可读性
  • 避免在一个表达式中使用过多的运算符
  • 不要过度依赖运算符优先级,明确性比简洁性更重要
运算符优先级示例
public class PrecedenceExample {
    public static void main(String[] args) {
        // 算术运算符优先级
        int result1 = 2 + 3 * 4;        // 14 (先算3*4=12,再算2+12=14)
        int result2 = (2 + 3) * 4;      // 20 (括号改变优先级)
        
        // 关系运算符与逻辑运算符
        boolean result3 = 5 > 3 && 2 < 4;  // true (先算关系运算,再算逻辑运算)
        boolean result4 = true || false && false;  // true (&&优先级高于||)
        
        // 赋值运算符优先级最低
        int a = 10;
        int b = a += 5 * 2;  // 先算5*2=10,再算a+=10,最后赋值给b
        System.out.println("a=" + a + ", b=" + b);  // a=20, b=20
        
        // 使用括号明确优先级
        int result5 = ((2 + 3) * 4) + 5;  // 25
        System.out.println("结果: " + result5);
    }
}

实际应用示例

计算器程序

SimpleCalculator.java
import java.util.Scanner;

public class SimpleCalculator {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.print("请输入第一个数字: ");
        double num1 = scanner.nextDouble();
        
        System.out.print("请输入运算符 (+, -, *, /, %): ");
        char operator = scanner.next().charAt(0);
        
        System.out.print("请输入第二个数字: ");
        double num2 = scanner.nextDouble();
        
        double result = 0;
        boolean validOperation = true;
        
        // 使用运算符进行计算
        switch (operator) {
            case '+':
                result = num1 + num2;
                break;
            case '-':
                result = num1 - num2;
                break;
            case '*':
                result = num1 * num2;
                break;
            case '/':
                if (num2 != 0) {
                    result = num1 / num2;
                } else {
                    System.out.println("错误:除数不能为零!");
                    validOperation = false;
                }
                break;
            case '%':
                if (num2 != 0) {
                    result = num1 % num2;
                } else {
                    System.out.println("错误:除数不能为零!");
                    validOperation = false;
                }
                break;
            default:
                System.out.println("错误:无效的运算符!");
                validOperation = false;
        }
        
        if (validOperation) {
            System.out.printf("%.2f %c %.2f = %.2f%n", num1, operator, num2, result);
        }
        
        scanner.close();
    }
}

成绩等级判断

GradeEvaluator.java
public class GradeEvaluator {
    public static void main(String[] args) {
        int score = 85;
        
        // 使用逻辑运算符进行条件判断
        String grade;
        if (score >= 90 && score <= 100) {
            grade = "A";
        } else if (score >= 80 && score < 90) {
            grade = "B";
        } else if (score >= 70 && score < 80) {
            grade = "C";
        } else if (score >= 60 && score < 70) {
            grade = "D";
        } else if (score >= 0 && score < 60) {
            grade = "F";
        } else {
            grade = "无效分数";
        }
        
        // 使用三元运算符判断是否及格
        String status = (score >= 60) ? "及格" : "不及格";
        
        System.out.println("分数: " + score);
        System.out.println("等级: " + grade);
        System.out.println("状态: " + status);
        
        // 使用复合条件判断奖学金资格
        boolean hasScholarship = (score >= 85) && (score <= 100);
        System.out.println("奖学金资格: " + (hasScholarship ? "有" : "无"));
    }
}

常见问题和注意事项

1. 整数除法问题

问题:为什么 5/2 的结果是 2 而不是 2.5

原因:这是整数除法,结果会舍去小数部分。

解决方案:至少有一个操作数应该是浮点数。

整数除法解决方案
int a = 5, b = 2;
double result1 = a / b;           // 2.0 (仍然是整数除法)
double result2 = (double)a / b;   // 2.5 (类型转换)
double result3 = a / 2.0;         // 2.5 (浮点除法)
double result4 = 1.0 * a / b;     // 2.5 (先转换为浮点数)

2. 自增自减的陷阱

避免:在一个表达式中多次使用自增自减运算符

原因:可能导致未定义的行为

自增自减注意事项
// 不好的做法 - 避免这样写
int a = 5;
int result = ++a + a++ + --a;  // 行为可能不确定

// 好的做法 - 分步骤进行
int a = 5;
a++;  // 先自增
int temp = a;  // 保存当前值
a--;  // 再自减
int result = temp + a;  // 明确的计算

3. 浮点数比较问题

问题:浮点数直接使用 == 比较可能不准确

原因:浮点数存储精度问题

解决方案:使用误差范围比较

浮点数比较
double a = 0.1 + 0.2;
double b = 0.3;

// 不好的做法
boolean equal1 = (a == b);  // 可能返回false

// 好的做法
double epsilon = 1e-10;
boolean equal2 = Math.abs(a - b) < epsilon;  // 使用误差范围比较

System.out.println("a = " + a);        // 0.30000000000000004
System.out.println("b = " + b);        // 0.3
System.out.println("直接比较: " + equal1);  // false
System.out.println("误差比较: " + equal2);  // true

最佳实践总结

✅ 推荐做法

  • 使用括号明确运算优先级,提高代码可读性
  • 字符串比较使用 equals() 方法
  • 利用短路求值提高程序性能
  • 使用复合赋值运算符简化代码
  • 浮点数比较使用误差范围
  • 避免在复杂表达式中使用自增自减

❌ 应该避免

  • 过度依赖运算符优先级记忆
  • 在一个表达式中多次使用自增自减
  • 字符串比较使用 ==
  • 忽略整数除法的特性
  • 浮点数直接使用 == 比较
  • 编写过于复杂的表达式

本章小结

本章我们深入学习了Java中的各种运算符:

运算符是Java编程的基础,熟练掌握它们的使用方法和注意事项,对于编写高质量的Java程序至关重要。在实际编程中,要注重代码的可读性和正确性,合理使用运算符来实现程序逻辑。

开始章节测试