首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java instanceof 模式匹配完整指南:類型檢查、強制轉型與 Java 16+ 新特性

     編輯:Java 程式設計入門

instanceof 基本語法與語義


// 傳統語法 (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 是所有類父類
StringCharSequence✅String 實作 CharSequence
ArrayListList✅實作關係
StringStringBuilder❌ 編譯錯誤無繼承關係
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 items = Arrays.asList(1, "hello", 3.14, new ArrayList<>());

for (Object item : items) {
    if (item instanceof Integer i) {
        System.out.println("整數: " + i * 2);
    } else if (item instanceof String s) {
        System.out.println("字串長度: " + s.length());
    } else if (item instanceof Double d) {
        System.out.println("浮點數: " + d);
    } else {
        System.out.println("其他: " + item.getClass().getSimpleName());
    }
}


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);
}

效能與最佳實踐

  1. 優先使用模式匹配:Java 16+ 程式碼更簡潔、型別安全
  2. 避免過度使用:多態設計 (介面/抽象方法) 通常優於 instanceof 分派
  3. 編譯期檢查:IDE 會提示不可能為 true 的檢查 (如 final 類檢查非子類)
  4. 密封類:配合 sealed 讓編譯器檢查 switch 窮盡性
  5. 效能: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()) { ... }
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved