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


1. instanceof關鍵字

如果你之前一直沒有怎么仔細了解過instanceof關鍵字,現在就來了解一下:

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

A instanceof B

注意:A是實例,而B則是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 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里面上轉型是安全的,子類對象可以轉換成為父類對象,接口實現類對象可以裝換成為接口對象。

對象aInterface沒有什么關系,所以返回false

那如果我們裝換成為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,不能使用基本數據類型,否則會報錯。

如果對象為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本身也是對象。

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM