Java 零基础教程

Java 运算符

运算符是任何编程语言的骨架,它们赋予了我们执行计算、比较数据以及控制程序流程的能力。在 Java 中,运算符是特殊的符号,用于对一个、两个或三个操作数(变量或值)执行特定操作。扎实掌握运算符是编写高效 Java 代码的关键前提。

本章将全面讲解算术、关系和逻辑运算符,为你提供在程序中处理数据和制定决策的必备工具。

1. 算术运算符 (Arithmetic Operators)

算术运算符用于执行数学计算。Java 提供了一组二元算术运算符(需要两个操作数参与)和一元运算符(只需要一个操作数参与)。

1.1 二元算术运算符

这些运算符使用两个操作数来进行计算。

运算符名称描述示例结果
+加法 (Addition)将两个操作数相加。5 + 38
-减法 (Subtraction)从第一个操作数中减去第二个操作数。5 - 32
*乘法 (Multiplication)将两个操作数相乘。5 * 315
/除法 (Division)第一个操作数除以第二个操作数。15 / 35
%取模/求余 (Modulus)返回除法运算后的余数。16 % 31

代码示例:

public class ArithmeticExample {
    public static void main(String[] args) {
        int a = 10;
        int b = 3;
        
        System.out.println("加法: " + (a + b));       // 输出: 13
        System.out.println("减法: " + (a - b));       // 输出: 7
        System.out.println("乘法: " + (a * b));       // 输出: 30
        System.out.println("除法: " + (a / b));       // 输出: 3 (注意:这里是整数除法)
        System.out.println("取模 (余数): " + (a % b)); // 输出: 1
    }
}

解析: 上面的代码演示了整数操作数下的二元算术运算。特别注意,当两个操作数都是整数时,除法运算符 / 执行的是整数除法,它会直接截断(舍弃)任何小数部分。

1.2 一元算术运算符

这些运算符仅对单一操作数执行操作。

运算符名称描述示例结果
+正号 (Unary plus)将 short, byte, char 提升为 int。对 int 或更大类型无影响。+55
-负号 (Unary minus)对表达式取反;翻转数字的正负号。-5-5
++自增 (Increment)将操作数的值增加 1。可作为前缀 (++a) 或后缀 (a++) 使用。a++++aa 变成 a+1
--自减 (Decrement)将操作数的值减少 1。可作为前缀 (--a) 或后缀 (a--) 使用。a----aa 变成 a-1

代码示例:

public class UnaryExample {
    public static void main(String[] args) {
        int a = 5;
        
        System.out.println("a 的初始值: " + a);             // 输出: 5
        System.out.println("正号: " + (+a));                // 输出: 5 (没有变化)
        System.out.println("负号: " + (-a));                // 输出: -5
        System.out.println("后缀自增 (Post-increment): " + (a++)); // 输出: 5 (先使用 a 的当前值打印,然后再将 a 加 1)
        System.out.println("后缀自增后的 a 值: " + a);        // 输出: 6
        System.out.println("前缀自减 (Pre-decrement): " + (--a));  // 输出: 5 (先将 a 减 1,然后再使用新值打印)
    }
}

解析: 自增 (++) 和自减 (--) 运算符的行为取决于它们是作为前缀还是后缀使用。

  • 前缀 (Prefix)(例如 ++a):变量 a 的值会先增加,然后再参与表达式的计算。
  • 后缀 (Postfix)(例如 a++):变量 a 的值会先参与表达式的计算,然后自身再增加。

1.3 复合赋值运算符

Java 还提供了复合赋值运算符,它们将算术运算和赋值操作合二为一,让代码更简洁。

运算符示例等价于
+=a += ba = a + b
-=a -= ba = a - b
*=a *= ba = a * b
/=a /= ba = a / b
%=a %= ba = a % b

代码示例:

public class CompoundAssignmentExample {
    public static void main(String[] args) {
        int a = 10;
        
        a += 5; // 等同于 a = a + 5
        System.out.println("a += 5: " + a); // 输出: 15
        
        a -= 3; // 等同于 a = a - 3
        System.out.println("a -= 3: " + a); // 输出: 12
        
        a *= 2; // 等同于 a = a * 2
        System.out.println("a *= 2: " + a); // 输出: 24
        
        a /= 4; // 等同于 a = a / 4
        System.out.println("a /= 4: " + a); // 输出: 6
        
        a %= 2; // 等同于 a = a % 2
        System.out.println("a %= 2: " + a); // 输出: 0
    }
}

2. 关系运算符 (Relational Operators)

关系运算符用于比较两个操作数。关系运算的结果永远是一个布尔值 (boolean):true(真) 或 false(假)。

运算符名称描述示例 (假设 a=5, b=10)结果
==等于如果两个操作数相等,返回 true,否则返回 false。a == bfalse
!=不等于如果两个操作数不相等,返回 true,否则返回 false。a != btrue
>大于如果第一个操作数大于第二个,返回 true,否则返回 false。a > bfalse
<小于如果第一个操作数小于第二个,返回 true,否则返回 false。a < btrue
>=大于或等于如果第一个操作数大于或等于第二个,返回 true,否则 false。a >= bfalse
<=小于或等于如果第一个操作数小于或等于第二个,返回 true,否则 false。a <= btrue

代码示例:

public class RelationalExample {
    public static void main(String[] args) {
        int a = 5;
        int b = 10;
        
        System.out.println("a == b: " + (a == b)); // 输出: false
        System.out.println("a != b: " + (a != b)); // 输出: true
        System.out.println("a > b: " + (a > b));   // 输出: false
        System.out.println("a < b: " + (a < b));   // 输出: true
        System.out.println("a >= b: " + (a >= b)); // 输出: false
        System.out.println("a <= b: " + (a <= b)); // 输出: true
        
        boolean isEqual = (a == 5);
        System.out.println("isEqual (a 等于 5 吗): " + isEqual); // 输出: true
    }
}

解析: 关系运算符在条件判断语句(下一模块会讲到)中被极其频繁地使用,用于根据特定条件控制程序的执行走向。像 a == 5 这样的比较表明,你不仅可以比较两个变量,也可以将变量与具体的字面量(固定值)进行比较。

3. 逻辑运算符 (Logical Operators)

逻辑运算符用于将两个或多个布尔表达式组合起来。逻辑运算的结果同样永远是一个布尔值:truefalse

运算符名称描述示例 (假设 a=true, b=false)结果
&&逻辑与 (AND)只有当两个操作数都为 true 时,才返回 true。具有短路特性。a && bfalse
||逻辑或 (OR)只要有至少一个操作数为 true,就返回 true。具有短路特性。a || btrue
!逻辑非 (NOT)反转操作数的布尔值。真变假,假变真。!afalse
&按位与 / 逻辑与行为类似 &&,但不具备短路特性,总是执行两边的评估。a & bfalse
|按位或 / 逻辑或行为类似 ||,但不具备短路特性,总是执行两边的评估。a | btrue
^逻辑异或 (XOR)当且仅当两个操作数一个为真,另一个为假时,返回 true。否则返回 false。a ^ btrue

代码示例:

public class LogicalExample {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        
        System.out.println("a && b: " + (a && b)); // 输出: false
        System.out.println("a || b: " + (a || b)); // 输出: true
        System.out.println("!a: " + (!a));         // 输出: false
        
        System.out.println("a & b: " + (a & b));   // 输出: false
        System.out.println("a | b: " + (a | b));   // 输出: true
        System.out.println("a ^ b: " + (a ^ b));   // 输出: true
    }
}

深度解析:

  • 短路求值 (Short-circuiting)&&|| 运算符具有短路行为。这意味着如果仅通过评估左边的操作数就能确定整个表达式的结果,Java 就不会再去执行/评估右边的操作数。
    • 例如在 a && b 中,如果 a 已经是 false,那么整个表达式注定是 false,此时 b 根本不会被执行。
    • 同理,在 a || b 中,如果 a 已经是 true,整个表达式注定是 trueb 同样被跳过。
  • 按位 vs 逻辑&| 原本是按位运算符,但也可以用于布尔值。与 &&|| 最大的区别是,它们没有短路特性,无论左边结果如何,右边的表达式都一定会执行。在日常逻辑判断中,强烈建议使用 &&||
  • 逻辑异或 (XOR)^ 只有在两边状态“相异”(一真一假)时才返回 true。如果两边都是真,或者都是假,它返回 false

3.1 组合运算符

你可以组合多个运算符来创建更复杂的表达式。可以使用小括号 () 来控制运算的优先级。

代码示例:

public class CombinedOperators {
    public static void main(String[] args) {
        int age = 25;
        boolean isStudent = true;
        
        // 检查某人是否有资格享受折扣(未满18岁 或者 是学生)
        boolean eligibleForDiscount = (age < 18) || isStudent;
        System.out.println("是否有折扣资格: " + eligibleForDiscount); // 输出: true
        
        // 检查某人是否是成年人 并且 不是学生
        boolean isAdultAndNotStudent = (age >= 18) && !isStudent;
        System.out.println("是成年人且不是学生: " + isAdultAndNotStudent); // 输出: false
    }
}

4. 运算符优先级 (Operator Precedence)

运算符优先级决定了在一个复杂的表达式中,各个运算符被执行的先后顺序。优先级高的运算符会先于优先级低的被评估。

以下是我们讲过的运算符的优先级排名(从高到低):

优先级运算符
1++, -- (后缀 Postfix)
2++, -- (前缀 Prefix), + (一元正号), - (一元负号), !
3*, /, %
4+, -
5==, !=, >, <, >=, <=
6&
7^
8|
9&&
10||
11=, +=, -=, *=, /=, %= (赋值类)

代码示例:

public class OperatorPrecedence {
    public static void main(String[] args) {
        int a = 5;
        int b = 10;
        int c = 2;
        
        int result = a + b * c; // 乘法的优先级高于加法
        System.out.println("a + b * c: " + result); // 输出: 25 (相当于 5 + (10 * 2))
        
        int result2 = (a + b) * c; // 小括号 () 拥有最高优先级,强制改变运算顺序
        System.out.println("(a + b) * c: " + result2); // 输出: 30 (相当于 (5 + 10) * 2)
        
        boolean boolResult = a > b || b < c && a == 5;
        System.out.println("不加括号的布尔组合: " + boolResult); //输出: false
        /* 执行顺序解析:
           1. 先算 && 两边:b < c 为 false (10 < 2)
           2. 关系运算 a == 5 为 true (5 == 5)
           3. false && true 结果为 false
           4. 再算 || 两边:a > b 为 false (5 > 10)
           5. 最终:false || false 结果为 false
        */
    }
}

解析: 牢记运算符优先级非常重要,它能防止程序得出意料之外的结果。当你不确定时,请果断使用小括号 (),这不仅能确保执行顺序绝对正确,还能极大提升代码的“人类可读性”。