Thinking in Java(2-4) 三元運算子、字串操作與型別轉換

在 Java 程式設計中,運算子扮演著關鍵角色。理解並善用各種運算子,能夠提升程式的效率與可讀性。本文將探討三元運算子、字串運算子以及型別轉換運算子,並透過範例程式碼深入解析。

一、三元運算子(Ternary If-Else Operator)

三元運算子是一種簡潔的條件判斷方式,其語法如下:

booleanExp ? value0 : value1
  • booleanExptrue 時,計算並返回 value0
  • booleanExpfalse 時,計算並返回 value1

範例:

public class TernaryIfElse {
  static int calculateUsingTernary(int i) {
    return i < 10 ? i * 100 : i * 10;
  }
  static int calculateUsingIfElse(int i) {
    if(i < 10)
      return i * 100;
    else
      return i * 10;
  }
  public static void main(String[] args) {
    print(calculateUsingTernary(9));  // 使用三元操作符計算,輸出: 900
    print(calculateUsingTernary(10)); // 使用三元操作符計算,輸出: 100
    print(calculateUsingIfElse(9));   // 使用標準if-else計算,輸出: 900
    print(calculateUsingIfElse(10));  // 使用標準if-else計算,輸出: 100
  }
} /* Output:
900
100
900
100
*/

說明:

  • calculateUsingTernary 使用三元運算子,實現了與 calculateUsingIfElse 相同的功能。
  • i 小於 10 時,返回 i * 100;否則,返回 i * 10
注意: 雖然三元運算子能使程式碼更為簡潔,但過度使用可能會降低可讀性。尤其在涉及複雜邏輯時,建議使用標準的 if-else 結構。

二、字串運算子 ++=

在 Java 中,++= 運算子被特別用於字串的串接操作,能夠方便地將字串與其他型別的資料連接。

範例:

public class StringOperators {
  public static void main(String[] args) {
    int x = 0, y = 1, z = 2;
    String s = "x, y, z ";
    System.out.println(s + x + y + z);
    System.out.println(x + " " + s); // Converts x to a String
    s += "(summed) = "; // Concatenation operator
    System.out.println(s + (x + y + z));
    System.out.println("" + x); // Shorthand for Integer.toString()
  }
} /* Output:
x, y, z 012
0 x, y, z
x, y, z (summed) = 3
0
*/

解析:

  • 第一行輸出: s + x + y + z,由於 s 是字串,後續的 xyz 會被自動轉換為字串,結果為 "x, y, z 012"
  • 第二行輸出: x + " " + sx 被自動轉換為字串並與其他字串串接。
  • 第三行輸出: 使用 +="(summed) = " 串接到 s,然後計算 x + y + z 的值並串接,結果為 "x, y, z (summed) = 3"
  • 第四行輸出: "" + x,這是一種簡便的將整數轉換為字串的方法。

注意:

  • + 運算子的第一個運算元是字串,則後續運算元會被自動轉換為字串。
  • 使用 += 運算子能直接將內容追加到原有的字串中,改變字串的值。
  • 編譯器會自動將雙引號內的文字視為 String 物件。

三、型別轉換運算子(Casting Operators)

在程式中,有時需要將一種資料型別轉換為另一種。Java 會在適當的情況下自動進行型別轉換,但在某些情況下需要明確地進行強制轉型。

範例:

public class Casting {
  public static void main(String[] args) {
    int i = 200;
    long lng = (long)i;    // 無需顯式轉換,因為 int 到 long 是 Widening
    lng = i;               // "Widening," so cast not really required
    long lng2 = (long)200; // 直接將字面量轉為 long
    lng2 = 200;            // 擴展轉換,自動處理
    // A "narrowing conversion":
    i = (int)lng2; // Cast required,因為 long 到 int 可能導致資料丟失
  }
} 

1. 窄化轉換與擴展轉換

  • 窄化轉換(Narrowing Conversion):
    • 將較大的資料型別轉換為較小的型別。
    • 可能造成資料遺失,因此需要顯式轉型。
  • 擴展轉換(Widening Conversion):
    • 將較小的資料型別轉換為較大的型別。
    • 不會造成資料遺失,編譯器會自動處理,無需顯式轉型。

2. 截斷與進位(Truncation and Rounding)

在進行窄化轉換時,特別是從浮點數轉換為整數時,會發生截斷或進位的問題。

截斷範例:

public class CastingNumbers {
  public static void main(String[] args) {
	double above = 0.7, below = 0.4;
	float fabove = 0.7f, fbelow = 0.4f;
	print("(int)above: " + (int)above);
	print("(int)below: " + (int)below);
	print("(int)fabove: " + (int)fabove);
	print("(int)fbelow: " + (int)fbelow);
  }
} /* Output:
(int)above: 0
(int)below: 0
(int)fabove: 0
(int)fbelow: 0
*/

說明:

  • 將浮點數轉換為整數時,會直接截斷小數部分,而非四捨五入。

進位範例:

若需要對浮點數進行四捨五入,可以使用 Math.round() 方法。

public class RoundingNumbers {
  public static void main(String[] args) {
	double above = 0.7, below = 0.4;
	float fabove = 0.7f, fbelow = 0.4f;
	print("Math.round(above): " + Math.round(above));
	print("Math.round(below): " + Math.round(below));
	print("Math.round(fabove): " + Math.round(fabove));
	print("Math.round(fbelow): " + Math.round(fbelow));
  }
} /* Output:
Math.round(above): 1
Math.round(below): 0
Math.round(fabove): 1
Math.round(fbelow): 0
*/

3. 型別提升(Promotion)

在表達式中,若包含不同的資料型別,較小的型別會自動提升為較大的型別,以確保運算的精確性。

示例:

  • floatdouble 運算時,float 會提升為 double
  • intlong 運算時,int 會提升為 long

注意:

  • 若需要將結果指定給較小的型別,需進行顯式轉型,否則會出現編譯錯誤。

四、Java 沒有 sizeof 運算子

在 C/C++ 中,sizeof() 函數用於獲取資料型別或物件所佔用的記憶體大小,這在不同位元系統間的程式碼移植中非常重要。

然而,Java 並未提供類似的 sizeof 運算子,原因如下:

  • 固定的資料型別大小: Java 的基本資料型別在所有平台上都有固定的大小。例如,int 永遠是 32 位元,long 永遠是 64 位元。
  • 跨平台性: Java 被設計為可移植的語言,虛擬機器(JVM)負責處理硬體細節,因此開發者無需關注底層硬體的差異。
  • 記憶體管理: Java 有自動垃圾回收機制,減少了直接管理記憶體的需求。

因此,在 Java 中,開發者無需使用 sizeof 來考慮資料型別的大小,這也使得程式更加簡潔和跨平台。


五、結論

本文深入探討了 Java 中的三元運算子、字串運算子以及型別轉換的使用方法和注意事項。理解並善用這些運算子,能夠使程式碼更加高效、簡潔,並提高可讀性。在實際開發中,建議根據具體需求選擇最適合的語法結構,並注意型別轉換可能帶來的潛在問題。