【Java基礎】-- instanceof 用法詳解

1. instanceof關鍵字

若是你以前一直沒有怎麼仔細瞭解過instanceof關鍵字,如今就來了解一下:html

instanceof實際上是java的一個二元操做符,和=,<,>這些是相似的,同時它也是被保留的關鍵字,主要的做用,是爲了測試左邊的對象,是否是右邊的類的實例,返回的是boolean值。java

A instanceof B

注意:A是實例,而B則是Class類數組

下面使用代碼測試一下:sass

class A{
}
interface InterfaceA{

}
class B extends A implements InterfaceA{

}
public class Test {
    public static void main(String[] args) {
        B b = new B();
        System.out.println(b instanceof B);
        System.out.println(b instanceof A);
        System.out.println(b instanceof InterfaceA);
        
        A a = new A();
        System.out.println(a instanceof InterfaceA);
    }
}

輸出結果以下:安全

true
true
true
false

從上面的結果,其實咱們能夠看出instanceof,至關於判斷當前對象能不能裝換成爲該類型,java裏面上轉型是安全的,子類對象能夠轉換成爲父類對象,接口實現類對象能夠裝換成爲接口對象。oracle

對象aInterface沒有什麼關係,因此返回falsejvm

那若是咱們裝換成爲Object了,它還能認出來是哪個類的對象麼?學習

public class Test {
    public static void main(String[] args) {
        Object o = new ArrayList<Integer>();
        System.out.println(o instanceof ArrayList);

        String str = "hello world";
        System.out.println(str instanceof String);
        System.out.println(str instanceof Object);
    }
}

上面的結果返回都是true,也就是認出來仍是哪個類的對象。同時咱們使用String對象測試的時候,發現對象既是String的實例,也是Object的實例,也印證了Java裏面全部類型都默認繼承了Obejct測試

可是值得注意的是,咱們只能使用對象來instanceof,不能使用基本數據類型,不然會報錯。code

若是對象爲null,那是什麼類型?

這個答案是:不知道什麼類型,由於null能夠轉換成爲任何類型,因此不屬於任何類型,instanceof結果會是false

具體的實現策略咱們能夠在官網找到:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.instanceof

若是Sobjectref所引用的對象的類,而T是已解析類,數組或接口的類型,則instanceof肯定是否 objectrefT的一個實例。S s = new A(); s instanceof T

  • 若是S是一個普通的(非數組)類,則:

    • 若是T是一個類類型,那麼S必須是T的同一個類,或者S必須是T的子類;
    • 若是T是接口類型,那麼S必須實現接口T。
  • 若是S是接口類型,則:

    • 若是T是類類型,那麼T必須是Object。
    • 若是T是接口類型,那麼T必定是與S相同的接口或S的超接口。
  • 若是S是表示數組類型SC的類[],即類型SC的組件數組,則:

    • 若是T是類類型,那麼T必須是Object。
    • 若是T是一種接口類型,那麼T必須是數組實現的接口之一(JLS§4.10.3)。
    • 若是T是一個類型爲TC的數組[],即一個類型爲TC的組件數組,那麼下列其中一個必須爲真:
      • TC和SC是相同的原始類型。
      • TC和SC是引用類型,類型SC能夠經過這些運行時規則轉換爲TC。

可是具體的底層原理我在知乎找到的R大 回答的相關問題,https://www.zhihu.com/question/21574535,看完以爲我太弱了...我是菜鳥...我確實是菜鳥

2. isInstance()方法

其實這個和上面那個是基本相同的,主要是這個調用者是Class對象,判斷參數裏面的對象是否是這個Class對象的實例。

class A {
}

interface InterfaceA {

}

class B extends A implements InterfaceA {

}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        System.out.println(B.class.isInstance(b));
        System.out.println(A.class.isInstance(b));
        System.out.println(InterfaceA.class.isInstance(b));

        A a = new A();
        System.out.println(InterfaceA.class.isInstance(a));
    }
}

歷史老是驚人的類似!!!

true
true
true
false

事實證實,這個isInstance(o)判斷的是o是否屬於當前Class類的實例.

不信?再來測試一下:

public class Test {
    public static void main(String[] args) {
        String s = "hello";
        System.out.println(String.class.isInstance(s)); 				// true
        System.out.println(Object.class.isInstance(s)); 				// true

        
        System.out.println("=============================");
        Object o = new ArrayList<String>();
        System.out.println(String.class.isInstance(o));					// false
        System.out.println(ArrayList.class.isInstance(o));			// true
        System.out.println(Object.class.isInstance(o));					// true
    }
}

能夠看出,其實就是裝換成爲Object,以前的類型信息仍是會保留着,結果和instance同樣,區別是:

  • instanceof :前面是實例對象,後面是類型
  • isInstance:調用者(前面)是類型對象,參數(後面)是實例對象

可是有一個區別哦😯,isInstance()這個方法,是可使用在基本類型上的,其實也不算是用在基本類型,而是自動作了裝箱操做。看下面👇:

System.out.println(Integer.class.isInstance(1));

參數裏面的1,其實會被裝箱成爲new Integer(1),因此這樣用不會報錯。

3. instanceof,isInstance,isAssignableFrom區別是什麼?

  • instanceof 判斷對象和類型之間的關係,是關鍵字,只能用於對象實例,判斷左邊的對象是否是右邊的類(包括父類)或者接口(包括父類)的實例化。
  • isInstance(Object o):判斷對象和類型之間的關係,判斷o是否是調用這個方法的class(包括父類)或者接口(包括父類)的實例化。
  • isAssignableFrom:判斷的是類和類之間的關係,調用者是否能夠由參數中的Class對象轉換而來。

注意:java裏面一切皆是對象,因此,class自己也是對象。

【做者簡介】
秦懷,公衆號【秦懷雜貨店】做者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。這個世界但願一切都很快,更快,可是我但願本身能走好每一步,寫好每一篇文章,期待和大家一塊兒交流。

此文章僅表明本身(本菜鳥)學習積累記錄,或者學習筆記,若有侵權,請聯繫做者覈實刪除。人無完人,文章也同樣,文筆稚嫩,在下不才,勿噴,若是有錯誤之處,還望指出,感激涕零~

相關文章
相關標籤/搜索