網頁

2018/8/25

Java instanceof 和 Class.isAssignableFrom(Class<?> cls)的區別

Java的instanceof關鍵字與Class類別的isAssignableFrom(Class<?> cls)方法都可用來判斷一個物件是否為某個類別或介面的子類別。但差異如下。

使用instanceof時在編譯期間要先知道被判斷的類別名稱。而isAssignableFrom(Class<?> cls)在編譯期間不需要知道被判斷的類別名稱,也就是在runtime時期才進行判斷。

例如下面範例,用來檢查兩個物件的型態是否為繼承關係。

public class Main {

    public static void main(String[] args) {

        Child child = new Child();
        Parent parent = new Parent();

        System.out.println(isSuperClass(child, parent)); // true
        System.out.println(isSuperClass(parent, child)); // false
    }

    /**
     * @param t1 Child object
     * @param t2 Parent object
     * @return
     */
    private static <T1, T2> boolean isSuperClass(T1 t1, T2 t2) {
        boolean result = false;
        result = t2.getClass().isAssignableFrom(t1.getClass());
        // result = t1 instanceof T2; // 編譯錯誤: Cannot perform instanceof check against type parameter T2. Use its erasure Object instead since further generic type information will be erased at runtime

        return result;
    }

}

class Child extends Parent {
}

class Parent {
}

在上面使用instanceof來判斷Generic型別時,會出現編譯錯誤:

Cannot perform instanceof check against type parameter T2. Use its erasure Object instead since further generic type information will be erased at runtime

也就是在執行期間Generic型別的資訊會被抹除,所以要改用isAssignableFrom(Class<?> cls)來判斷。


下面示另一個使用isAssignableFrom(Class<?> cls)的範例,例如一個方法可將List中的物件轉型成特定的型別。

public <T> List<T> castCollection(List<?> srcList, Class<T> cls) {
    List<T> list = new ArrayList<T>();
    for (Object obj : srcList) {
        if (null == obj) {
            continue;
        }
        if (cls.isAssignableFrom(obj.getClass())) {
            T t = (T) obj;
            list.add(t);
        }
    }
    return list;
}

因此isAssignableFrom(Class<?> cls)的使用時機為在編譯期間無法確定要判斷的類別。


參考:

沒有留言:

張貼留言