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)
的使用時機為在編譯期間無法確定要判斷的類別。
參考:
沒有留言:
張貼留言