【Java基礎】-- isAssignableFrom的用法詳細解析
最近在java的原始碼中總是可以看到isAssignableFrom()
這個方法,到底是幹嘛的?怎麼用?
1. isAssignableFrom()是幹什麼用的?
首先我們必須知道的是,java裡面一切皆物件,類本身也是會當成物件來處理,主要體現在類的.class
檔案,其實載入到java虛擬機器之後,也是一個物件,它就是Class
物件,全限定類名:java.lang.Class
。
那這個isAssignableFrom()
其實就是Class物件的一個方法:
/** * Determines if the class or interface represented by this * {@code Class} object is either the same as, or is a superclass or * superinterface of, the class or interface represented by the specified * {@code Class} parameter. It returns {@code true} if so; * otherwise it returns {@code false}. If this {@code Class} * object represents a primitive type, this method returns * {@code true} if the specified {@code Class} parameter is * exactly this {@code Class} object; otherwise it returns * {@code false}. * * <p> Specifically, this method tests whether the type represented by the * specified {@code Class} parameter can be converted to the type * represented by this {@code Class} object via an identity conversion * or via a widening reference conversion. See <em>The Java Language * Specification</em>, sections 5.1.1 and 5.1.4 , for details. * * @param cls the {@code Class} object to be checked * @return the {@code boolean} value indicating whether objects of the * type {@code cls} can be assigned to objects of this class * @exception NullPointerException if the specified Class parameter is * null. * @since JDK1.1 */ public native boolean isAssignableFrom(Class<?> cls);
用native
關鍵字描述,說明是一個底層方法,實際上是使用c/c++實現的,java裡面沒有實現,那麼這個方法是幹什麼的呢?我們從上面的註釋可以解讀:
如果是A.isAssignableFrom(B)
確定一個類(B)是不是繼承來自於另一個父類(A),一個介面(A)是不是實現了另外一個介面(B),或者兩個類相同。主要,這裡比較的維度不是例項物件,而是類本身,因為這個方法本身就是Class
類的方法,判斷的肯定是和類資訊相關的。
也就是判斷當前的Class物件所表示的類,是不是引數中傳遞的Class物件所表示的類的父類,超介面,或者是相同的型別。是則返回true,否則返回false。
2.程式碼實驗測試
2.1 父子繼承關係測試
class A{ } class B extends A{ } class C extends B{ } public class test { public static void main(String[] args) { A a = new A(); B b = new B(); B b1 = new B(); C c = new C(); System.out.println(a.getClass().isAssignableFrom(a.getClass())); System.out.println(a.getClass().isAssignableFrom(b.getClass())); System.out.println(a.getClass().isAssignableFrom(c.getClass())); System.out.println(b1.getClass().isAssignableFrom(b.getClass())); System.out.println(b.getClass().isAssignableFrom(c.getClass())); System.out.println("====================================="); System.out.println(A.class.isAssignableFrom(a.getClass())); System.out.println(A.class.isAssignableFrom(b.getClass())); System.out.println(A.class.isAssignableFrom(c.getClass())); System.out.println("====================================="); System.out.println(Object.class.isAssignableFrom(a.getClass())); System.out.println(Object.class.isAssignableFrom(String.class)); System.out.println(String.class.isAssignableFrom(Object.class)); } }
執行結果如下:
true
true
true
true
true
=====================================
true
true
true
=====================================
true
true
false
從執行結果來看,C
繼承於B
,B
繼承於A
,那麼任何一個類都可以isAssignableFrom
其本身,這個從中文意思來理解就是可以從哪一個裝換而來,自身裝換而來肯定是沒有問題的,父類可以由子類裝換而來也是沒有問題的,所以A可以由B裝換而來,同時也可以由子類的子類轉換而來。
上面的程式碼也說明一點,所有的類,其最頂級的父類也是Object
,也就是所有的型別都可以轉換成為Object
。
2.2 介面的實現關係測試
interface InterfaceA{
}
class ClassB implements InterfaceA{
}
class ClassC implements InterfaceA{
}
class ClassD extends ClassB{
}
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(InterfaceA.class.isAssignableFrom(InterfaceA.class));
System.out.println(InterfaceA.class.isAssignableFrom(ClassB.class));
System.out.println(InterfaceA.class.isAssignableFrom(ClassC.class));
System.out.println(ClassB.class.isAssignableFrom(ClassC.class));
System.out.println("============================================");
System.out.println(ClassB.class.isAssignableFrom(ClassD.class));
System.out.println(InterfaceA.class.isAssignableFrom(ClassD.class));
}
}
輸出結果如下:
true
true
true
false
============================================
true
true
從上面的結果看,其實介面的實現關係和類的實現關係是一樣的,沒有什麼區別,但是如果B
和C
都實現了同一個介面,他們之間其實是不能互轉的。
如果B
實現了介面A
,D
繼承了B
,實際上D
是可以上轉為A介面的,相當於D
間接實現了A
,這裡也說明了一點,其實繼承關係和介面實現關係,在isAssignableFrom()
的時候是一樣的,一視同仁的。
3.總結
isAssignableFrom
是用來判斷子類和父類的關係的,或者介面的實現類和介面的關係的,預設所有的類的終極父類都是Object
。如果A.isAssignableFrom(B)
結果是true,證明B
可以轉換成為A
,也就是A
可以由B
轉換而來。
這個方法在我們平時使用的不多,但是很多原始碼裡面判斷兩個類之間的關係的時候,(注意:是兩個類的關係,不是兩個類的例項物件的關係!!!),會使用到這個方法來判斷,大概因為框架程式碼或者底層程式碼都是經過多層抽象,做到容易拓展和解耦合,只能如此。
【作者簡介】:
秦懷,公眾號【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。這個世界希望一切都很快,更快,但是我希望自己能走好每一步,寫好每一篇文章,期待和你們一起交流。
此文章僅代表自己(本菜鳥)學習積累記錄,或者學習筆記,如有侵權,請聯絡作者核實刪除。人無完人,文章也一樣,文筆稚嫩,在下不才,勿噴,如果有錯誤之處,還望指出,感激不盡~