Thinking in Java(2-4) 三元運算子、字串操作與型別轉換
在 Java 程式設計中,運算子扮演著關鍵角色。理解並善用各種運算子,能夠提升程式的效率與可讀性。本文將探討三元運算子、字串運算子以及型別轉換運算子,並透過範例程式碼深入解析。
一、三元運算子(Ternary If-Else Operator)
三元運算子是一種簡潔的條件判斷方式,其語法如下:
booleanExp ? value0 : value1
- 當
booleanExp
為true
時,計算並返回value0
。 - 當
booleanExp
為false
時,計算並返回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
是字串,後續的x
、y
、z
會被自動轉換為字串,結果為"x, y, z 012"
。 - 第二行輸出:
x + " " + s
,x
被自動轉換為字串並與其他字串串接。 - 第三行輸出: 使用
+=
將"(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)
在表達式中,若包含不同的資料型別,較小的型別會自動提升為較大的型別,以確保運算的精確性。
示例:
float
與double
運算時,float
會提升為double
。int
與long
運算時,int
會提升為long
。
注意:
- 若需要將結果指定給較小的型別,需進行顯式轉型,否則會出現編譯錯誤。
四、Java 沒有 sizeof
運算子
在 C/C++ 中,sizeof()
函數用於獲取資料型別或物件所佔用的記憶體大小,這在不同位元系統間的程式碼移植中非常重要。
然而,Java 並未提供類似的 sizeof
運算子,原因如下:
- 固定的資料型別大小: Java 的基本資料型別在所有平台上都有固定的大小。例如,
int
永遠是 32 位元,long
永遠是 64 位元。 - 跨平台性: Java 被設計為可移植的語言,虛擬機器(JVM)負責處理硬體細節,因此開發者無需關注底層硬體的差異。
- 記憶體管理: Java 有自動垃圾回收機制,減少了直接管理記憶體的需求。
因此,在 Java 中,開發者無需使用 sizeof
來考慮資料型別的大小,這也使得程式更加簡潔和跨平台。
五、結論
本文深入探討了 Java 中的三元運算子、字串運算子以及型別轉換的使用方法和注意事項。理解並善用這些運算子,能夠使程式碼更加高效、簡潔,並提高可讀性。在實際開發中,建議根據具體需求選擇最適合的語法結構,並注意型別轉換可能帶來的潛在問題。
Comments ()