Java Class.cast() 與 Cast 運算符
一、簡介
Java 中的型別轉換是一個基本概念,它允許將一種資料型別轉換為另一種資料型別。這是有效操作程序中的物件和變數的關鍵過程。在現實世界中,鑄造類似於將測量值從一種單位轉換為另一種單位,例如將英寸轉換為厘米。
在 Java 中,當超類別引用子類別的物件時,通常在處理多態性時使用強制轉換。然後,我們需要存取子類別的特定方法或屬性,並依靠強制轉換來實現相同的目的。這是至關重要的,因為 Java 是一種強型別語言,且變數具有特定的資料型別。
在本教程中,讓我們深入研究這兩個選項的細微差別,評估它們的用途,然後重點介紹每個選項的最佳實踐。
2. 定義我們的用例
為了說明cast運算子和Class.cast(),我們將考慮一個涉及電玩角色層次結構的有趣用例。
我們將建立一個具有超類別Character和子類別Warrior和Commander的範例。我們的目標是學習如何將通用Character物件轉換為特定的子類別類型以存取其獨特的方法。
該用例涉及創建Warrior和Commander的實例。這些實例儲存在Character物件清單中。隨後,它們被檢索並轉換回其特定類型。這種轉換允許呼叫特定於子類別的方法。
3. 定義模型類
讓我們先定義我們的第一個子類,一個名為Warrior Character ,其方法為obeyCommand() :
public class Warrior extends Character {
public void obeyCommand(String command) {
logger.info("Warrior {} obeys a command {}", this.getName(), command);
}
}
現在,讓我們建立名為 Commander 的第二個Character子類別Commander.這實作了向戰士發出指令的issueCommand()方法:
public class Commander extends Character {
public void issueCommand(String command) {
log.info("Commander {} issues a command {}: ", this.getName(), command);
}
}
4.cast 操作ast
在 Java 中, cast運算子是將一種物件類型轉換為另一種物件類型的簡單選項。**我們使用括號來指定目標類型。**
為了示範這一點,讓我們寫一個新類別PlayGame ,它會創建多個角色(每種類型一個)。然後它嘗試執行命令或發出隨機命令,這取決於角色是Warrior還是Commander.
讓我們先在新類別PlayGame:
public class PlayGame {
public List<Character> buildCharacters() {
List<Character> characters = new ArrayList<>();
characters.add(new Commander("Odin"));
characters.add(new Warrior("Thor"));
return characters;
}
}
我們現在將添加基於每個角色玩遊戲的能力。根據我們的性格,我們要么執行給定的命令,要么發出新的命令。讓我們使用cast轉換運算子來示範這一點:
public void playViaCastOperator(List<Character> characters, String command) {
for (Character character : characters) {
if (character instanceof Warrior) {
Warrior warrior = (Warrior) character;
warrior.obeyCommand(command);
}
else if (character instanceof Commander) {
Commander commander = (Commander)
character; commander.issueCommand(command);
}
}
}
在上面的程式碼中,我們使用了向下轉型的方法,這意味著我們將父類別的實例限制為衍生類別。這樣,可用的操作僅限於衍生類別的方法。
讓我們分解一下我們的實作並了解步驟:
- 在我們的
PlayGame類別中,我們定義了一個方法playViaCastOperator(),它被賦予一個字元列表和一個指令 - 我們遍歷角色清單並根據角色是
Warrior還是Commander.我們使用instanceof關鍵字來確認類型 - 如果
Character是Warrior,我們使用cast轉換運算子 (Warrior) 來取得Warrior的實例並呼叫obeyCommand()方法 - 如果
Character是Commander,我們使用cast轉換運算子(Commander)來取得Commander的實例並呼叫issueCommand()方法
Class.cast()方法
讓我們看看如何使用屬於java.lang.Class一部分的**Class.cast()方法來實現相同的目的**。
現在,我們將在PlayGame類別中新增一個playViaClassCast()方法來檢視此方法:
public void playViaClassCast(List<Character> characters, String command) {
for (Character character : characters) {
if (character instanceof Warrior) {
Warrior warrior = Warrior.class.cast(character);
warrior.obeyCommand(command);
} else if (character instanceof Commander) {
Commander commander = Commander.class.cast(character);
commander.issueCommand(command);
}
}
}
正如我們所看到的,我們現在使用Class.cast() 將Character轉換為Warrior或Commander.
6. Class.cast()與cast運算符
現在讓我們根據不同的標準來比較這兩種方法:
| 標準 | **Class.cast()** |
cast轉換運算符 |
|---|---|---|
| 可讀性和簡單性 | 使類型轉換明確且清晰,尤其是在類型安全受到關注的複雜或通用程式碼中 | 用於簡單的轉換操作,其中類型在編譯時已知,有利於可讀性 |
| --- | --- | --- |
| 類型安全 | 透過明確類型檢查來提供更好的類型安全性。這在泛型程式設計中特別有用,在泛型程式設計中,類型在運行時之前是未知的,可確保類型安全的轉換並避免類別轉換問題 | 不提供顯式類型檢查,如果誤用可能會導致可怕的ClassCastException |
| --- | --- | --- |
| 表現 | 由於額外的方法呼叫而增加了輕微的開銷,但這通常很小,並且被複雜場景中類型安全的好處所抵消 | 由於它是直接類型轉換,因此提供了輕微的效能優勢,但在大多數實際應用中差異可以忽略不計 |
| --- | --- | --- |
| 程式碼維護 | 提高複雜或通用程式碼庫的清晰度,使維護和調試類型問題變得更加容易 | 在簡單場景中更易於使用和理解,使直接轉換的程式碼維護更簡單 |
| --- | --- | --- |
| 靈活性 | 更適合泛型程式設計或嚴重依賴反射的框架,確保類型安全性和清晰度 | 對於泛型程式來說不是一個很好的選擇 |
| --- | --- | --- |
我們應該始終在透過instanceof運算子進行轉換之前驗證類型,以避免類別轉換異常。利用函式庫和框架可以幫助更穩健地處理轉換和類型檢查。
七、結論
在本文中,我們討論了 Java 中的兩種轉換選項,並透過相關用例和實際比較了解了它們的限制和優點。
使用強制轉換運算子可以使強制轉換過程更加簡潔。與Class.cast()方法相比,它更簡潔。然而,這兩種方法都有其優點和缺點。我們需要仔細考慮這些優點和缺點。選擇取決於我們的用例和實現上下文。
考慮到上表中列出的標準,我們總是可以做出正確的鑄造選擇。
像往常一樣,我們可以在 GitHub 上找到完整的程式碼範例。