// 傳統語法 (Java 1-15)
if (obj instanceof String) {
String s = (String) obj; // 需顯式強制轉型
System.out.println(s.length());
}
用於運行時檢查物件是否為某類型 (類、介面、子類、實現類) 的實例
返回 boolean:true 表示是該類型或其子類型
null instanceof AnyType 永遠返回 false (不拋 NPE)
編譯期檢查:左操作數類型必須與右類型有繼承/實現關係,否則編譯錯誤
Java 16+ 模式匹配 (Pattern Matching for instanceof) - JEP 394
// 新語法:宣告模式變數,自動完成轉型
if (obj instanceof String s) { // s 為模式變數,作用域限於 if 區塊
System.out.println(s.length()); // 直接使用,無需強轉
// s 在此處可見
}
// s 在此處不可見 (作用域結束)
// 配合邏輯運算子
if (obj instanceof String s && s.length() > 10) {
System.out.println("長字串: " + s);
}
// switch 表達式搭配 (Java 17+)
String formatted = switch (obj) {
case Integer i -> "整數: " + i;
case String s -> "字串: " + s;
case List> list -> "列表大小: " + list.size();
default -> "未知類型";
};
型別檢查規則詳解
左操作數編譯類型
右類型
合法性
說明
Object
任意類/介面
✅
Object 是所有類父類
String
CharSequence
✅
String 實作 CharSequence
ArrayList
List
✅
實作關係
String
StringBuilder
❌ 編譯錯誤
無繼承關係
final class
非自身類
❌ 編譯錯誤
final 類無子類
實戰應用場景
1. 訪問者模式替代品 (密封類 + switch)
// Java 17+ sealed 類
sealed interface Expr permits Const, Add, Mul {}
record Const(int value) implements Expr {}
record Add(Expr left, Expr right) implements Expr {}
record Mul(Expr left, Expr right) implements Expr {}
int eval(Expr e) {
return switch (e) {
case Const(int v) -> v;
case Add(Expr l, Expr r) -> eval(l) + eval(r);
case Mul(Expr l, Expr r) -> eval(l) * eval(r);
};
}
2. 類型安全的異構集合處理
List
3. JSON 反序列化多態處理
// 假設 JSON 包含 type 欄位區分實際類型
public class AnimalDeserializer extends JsonDeserializer {
@Override
public Animal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode node = p.getCodec().readTree(p);
String type = node.get("type").asText();
return switch (type) {
case "dog" -> p.getCodec().treeToValue(node, Dog.class);
case "cat" -> p.getCodec().treeToValue(node, Cat.class);
default -> throw new IllegalArgumentException("未知動物類型: " + type);
};
}
}
4. 防禦性編程:安全轉型工具方法
public class TypeUtils {
// 安全轉型:失敗返回 null 而非拋 ClassCastException
@SuppressWarnings("unchecked")
public static T castOrNull(Object obj, Class clazz) {
return clazz.isInstance(obj) ? clazz.cast(obj) : null;
}
// Java 16+ 模式匹配版
public static Optional asOptional(Object obj, Class clazz) {
return obj instanceof T t ? Optional.of(t) : Optional.empty();
}
}
// 使用
String s = TypeUtils.castOrNull(obj, String.class);
Optional opt = TypeUtils.asOptional(obj, String.class);
進階:instanceof vs getClass() vs isInstance()
方法
語義
繼承敏感
null 處理
用途
obj instanceof Type
是否為 Type 或子類型
✅ 是
false
多型檢查、模式匹配
obj.getClass() == Type.class
精確類型相等
❌ 否
NPE
精確類型判斷、equals 實作
Type.class.isInstance(obj)
動態類型檢查
✅ 是
false
泛型類型 Token、反射場景
// equals 中正確使用 getClass() (而非 instanceof)
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; // 精確類型
MyClass that = (MyClass) o;
return Objects.equals(field, that.field);
}
效能與最佳實踐
優先使用模式匹配:Java 16+ 程式碼更簡潔、型別安全
避免過度使用:多態設計 (介面/抽象方法) 通常優於 instanceof 分派
編譯期檢查:IDE 會提示不可能為 true 的檢查 (如 final 類檢查非子類)
密封類:配合 sealed 讓編譯器檢查 switch 窮盡性
效能:instanceof 為 JVM 內部指令,極快 (單指令級),無顯著開銷
遷移指南:舊代碼現代化
// Before (Java 8)
if (obj instanceof String) {
String s = (String) obj;
process(s);
}
// After (Java 16+)
if (obj instanceof String s) {
process(s);
}
// 複雜條件
// Before
if (obj instanceof List) {
List> list = (List>) obj;
if (!list.isEmpty()) { ... }
}
// After
if (obj instanceof List> list && !list.isEmpty()) { ... }