HOWTO · Java
Java Not InstanceOf
本教程演示如何在 Java 中否定 instanceof 關鍵字。
本頁內容
在 Java 中,沒有獨立的「非 instanceof」運算子。若要否定整個型別檢查,請寫成 !(object instanceof Type)。本指南會說明這個運算式的意義、繼承與 null 如何影響結果,以及如何用它篩選物件。
Java 中 instanceof 的檢查內容
instanceof 運算子會判斷非 null 物件是否可視為指定的參考型別:該型別可以是類別、父類別,或執行時類別相容的介面。例如,從子類別建立的物件,也會符合對其父類別及其實作介面的檢查。這個運算式會產生布林值,因此可用於 if 條件,也能與其他布林運算式組合。
左側必須是參考運算式,右側型別也必須與它相容。若兩個型別不可能有關聯,Java 會拒絕某些檢查。instanceof 不會轉換物件,只會判斷型別關係是否成立。檢查成功後可作為轉型前的判斷依據,但轉型本身是另一個操作。
如何否定 instanceof 檢查
將完整的型別檢查放在邏輯 NOT 運算子的括號內:!(object instanceof Type)。括號能清楚表示 ! 會反轉整個 instanceof 運算式的布林結果。物件符合 Type 時,內層檢查為 true,否定後的條件便是 false;物件不符合時,內層檢查為 false,否定後的條件便是 true。
你也可能會看到 object instanceof Type == false 這種寫法,但 !(object instanceof Type) 更直接地表達相同意思,也更容易閱讀。當你要處理的是不符合型別的情況時,可在 if 陳述式中使用否定形式。
範例:依型別篩選物件
這個完整範例會保留不是貓的動物並進行處理。程式會先為每個元素執行檢查,再於非貓的分支中使用該元素。
執行此範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import java.util.List;
public class Main {
interface Animal {}
static class Dog implements Animal {}
static class Cat implements Animal {}
public static void main(String[] args) {
List<Animal> animals = List.of(new Dog(), new Cat(), new Dog());
for (Animal animal : animals) {
if (!(animal instanceof Cat)) {
System.out.println("Processing " + animal.getClass().getSimpleName());
}
}
}
}
Processing Dog
Processing Dog
範例輸出會顯示兩行 Processing Dog。這是程式原有的英文標籤,為了保留範例內容而維持英文。
繼承與 null 如何影響結果
子類別的實例除了符合自身類別的 instanceof 檢查,也符合其父類別與所實作介面的檢查。因此,若物件是某個父類別之子類別的實例,否定對該父類別的檢查會得到 false。請謹慎選擇條件中的型別:檢查較廣泛的父類別,會排除比檢查特定子類別更多的物件。
運算式 null instanceof Type 的結果永遠是 false。因此,當 value 是 null 時,!(value instanceof Type) 會是 true。如果後續分支假設物件不是 null,或會呼叫它的方法,就必須另外處理這點;單靠否定型別檢查,無法確認該值不是 null。
何時使用否定的 instanceof 檢查
當不符合型別的情況正好描述你要執行的工作時,可使用 !(value instanceof Type),例如處理混合集合時略過某一種項目。讓條件緊鄰它所控制的分支,並選用能反映預期排除對象的明確型別。如果符合與不符合的兩種情況都需要大量處理邏輯,明確列出分支可能更容易理解。
負向檢查不會讓物件自動適合轉型成其他型別。轉型或呼叫型別專屬方法之前,請先確認這些操作所需的正向型別條件。如果值可能不存在,也要考慮 null 的行為。清楚的檢查有助於讀者檢視條件的含義,以及後續程式碼依賴的假設。