1. 程式人生 > 實用技巧 >【Java基礎】-- isAssignableFrom的用法詳細解析

【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繼承於BB繼承於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

從上面的結果看,其實介面的實現關係和類的實現關係是一樣的,沒有什麼區別,但是如果BC都實現了同一個介面,他們之間其實是不能互轉的。

如果B實現了介面AD繼承了B,實際上D是可以上轉為A介面的,相當於D間接實現了A,這裡也說明了一點,其實繼承關係和介面實現關係,在isAssignableFrom()的時候是一樣的,一視同仁的。

3.總結

isAssignableFrom是用來判斷子類和父類的關係的,或者介面的實現類和介面的關係的,預設所有的類的終極父類都是Object。如果A.isAssignableFrom(B)結果是true,證明B可以轉換成為A,也就是A可以由B轉換而來。

這個方法在我們平時使用的不多,但是很多原始碼裡面判斷兩個類之間的關係的時候,(注意:是兩個類的關係,不是兩個類的例項物件的關係!!!),會使用到這個方法來判斷,大概因為框架程式碼或者底層程式碼都是經過多層抽象,做到容易拓展和解耦合,只能如此。

【作者簡介】
秦懷,公眾號【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。這個世界希望一切都很快,更快,但是我希望自己能走好每一步,寫好每一篇文章,期待和你們一起交流。

此文章僅代表自己(本菜鳥)學習積累記錄,或者學習筆記,如有侵權,請聯絡作者核實刪除。人無完人,文章也一樣,文筆稚嫩,在下不才,勿噴,如果有錯誤之處,還望指出,感激不盡~