Thinking in Java(2-2) 深入理解算術與關係運算子

Thinking in Java(2-2) 深入理解算術與關係運算子
Photo by orbtal media / Unsplash

Java 中的運算子是程式語言的核心部分,理解並善用這些運算子可以大幅提升程式的效率和可讀性。本文將深入探討 Java 的算術運算子、一元運算子、自動遞增與遞減運算子,以及關係運算子,並透過範例程式碼來加深理解。

算術運算子(Mathematical Operators)

Java 的算術運算子與大多數程式語言,特別是 C/C++,基本一致,包括加(+)、減(-)、乘(*)、除(/)和取餘(%)等。

以下是一個示範如何使用這些運算子的範例:

public class MathOps {
  public static void main(String[] args) {
    Random rand = new Random(47); // 創建一個隨機數生成器
    int i, j, k;
    // 從 1 到 100 隨機選取數值:
    j = rand.nextInt(100) + 1;
    System.out.println("j : " + j);
    k = rand.nextInt(100) + 1;
    System.out.println("k : " + k);
    i = j + k;
    System.out.println("j + k : " + i);
    i = j - k;
    System.out.println("j - k : " + i);
    i = k / j;
    System.out.println("k / j : " + i);
    i = k * j;
    System.out.println("k * j : " + i);
    i = k % j;
    System.out.println("k % j : " + i);
    j %= k;
    System.out.println("j %= k : " + j);

    // 浮點數運算測試:
    float u, v, w; // 適用於 double 型別
    v = rand.nextFloat();
    System.out.println("v : " + v);
    w = rand.nextFloat();
    System.out.println("w : " + w);
    u = v + w;
    System.out.println("v + w : " + u);
    u = v - w;
    System.out.println("v - w : " + u);
    u = v * w;
    System.out.println("v * w : " + u);
    u = v / w;
    System.out.println("v / w : " + u);

    // 以下運算也適用於 char、byte、short、int、long 和 double:
    u += v;
    System.out.println("u += v : " + u);
    u -= v;
    System.out.println("u -= v : " + u);
    u *= v;
    System.out.println("u *= v : " + u);
    u /= v;
    System.out.println("u /= v : " + u);
  }
}
/* 輸出:
j : 59
k : 56
j + k : 115
j - k : 3
k / j : 0
k * j : 3304
k % j : 56
j %= k : 3
v : 0.5309454
w : 0.0534122
v + w : 0.5843576
v - w : 0.47753322
v * w : 0.028358962
v / w : 9.940527
u += v : 10.471473
u -= v : 9.940527
u *= v : 5.2778773
u /= v : 9.940527
*/

在這個程式中,我們使用 Random 類別生成隨機數,並對整數和浮點數進行基本的算術運算,展示了各種運算子的使用方式。

一元加號與減號運算子(Unary Plus and Minus Operators)

一元加號和減號運算子是基本的算術運算子,在 Java 中具有特定的用途:

  • 一元減號(-:用於將數字的正負號反轉。例如,若 a = 5,則 -a 的值為 -5
  • 一元加號(+:通常對數值沒有影響,但可以用來將較小的資料型別(如 byteshort)提升為 int

範例:

int x, a = 5, b = -3;
x = -a;        // x 的值為 -5
x = a * -b;    // x 的值為 -15
x = a * (-b);  // x 的值同樣為 -15

自動遞增與遞減(Auto Increment and Decrement)

自動遞增和遞減運算子可以簡化對變數進行加減 1 的操作:

  • a++ 等價於 a = a + 1
  • a-- 等價於 a = a - 1

根據運算子的位置,分為:

  • 前置遞增(++i:先對變數進行遞增,再使用變數的值。
  • 後置遞增(i++:先使用變數的值,再對變數進行遞增。

範例:

public class AutoInc {
  public static void main(String[] args) {
    int i = 1;
    System.out.println("i : " + i);
    System.out.println("++i : " + ++i); // 前置遞增
    System.out.println("i++ : " + i++); // 後置遞增
    System.out.println("i : " + i);
    System.out.println("--i : " + --i); // 前置遞減
    System.out.println("i-- : " + i--); // 後置遞減
    System.out.println("i : " + i);
  }
}
/* 輸出:
i : 1
++i : 2
i++ : 2
i : 3
--i : 2
i-- : 2
i : 1
*/
注意: ++-- 是除了指定運算子以外,唯一具有「副作用」的運算子,會改變運算元的值,而不僅僅是使用其值。

關係運算子(Relational Operators)

關係運算子用於比較兩個運算元,並返回一個 boolean 值(truefalse)。常見的關係運算子包括:

  • 等於:==
  • 不等於:!=
  • 大於:>
  • 小於:<
  • 大於等於:>=
  • 小於等於:<=

範例:

public class Equivalence {
  public static void main(String[] args) {
    Integer n1 = Integer.valueOf(47);
    Integer n2 = Integer.valueOf(47);
    System.out.println(n1 == n2);      // 比較參考
    System.out.println(n1 != n2);      // 比較參考
  }
}
/* 輸出:
false
true
*/
提示: 從 Java 9 開始,建議使用 Integer.valueOf(47) 來取代 new Integer(47),因為 Integer.valueOf() 可以利用整數快取來提高效能並減少記憶體使用。

在上述範例中,n1n2 是兩個不同的 Integer 物件,使用 ==!= 比較時,實際上比較的是兩個物件的參考,而不是它們的值。

為了正確比較兩個物件的值,應該使用 equals() 方法:

public class EqualsMethod {
  public static void main(String[] args) {
    Integer n1 = Integer.valueOf(47);
    Integer n2 = Integer.valueOf(47);
    System.out.println(n1.equals(n2));  // 比較值
  }
}
/* 輸出:
true
*/

對於自訂的類別,如果沒有覆寫 equals() 方法,則 equals() 的預設行為仍然是比較物件的參考,而非內容。

範例:

class Value {
  int i;
}

public class EqualsMethod2 {
  public static void main(String[] args) {
    Value v1 = new Value();
    Value v2 = new Value();
    v1.i = v2.i = 100;
    System.out.println(v1.equals(v2));  // 預設比較參考
  }
}
/* 輸出:
false
*/

要讓自訂類別的 equals() 方法比較內容,需要在類別中覆寫 equals() 方法。


結論

理解 Java 中的各種運算子及其行為對於撰寫高效、可靠的程式至關重要。本文探討了算術運算子、一元運算子、自動遞增與遞減運算子,以及關係運算子的用法和注意事項。希望透過這些內容,您能夠在實際開發中更靈活地運用這些運算子,提高程式的品質和效率。