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
里面上轉型是安全的,子類對象可以轉換成為父類對象,接口實現類對象可以裝換成為接口對象。
對象a
和Interface
沒有什么關系,所以返回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
如果S
是objectref
所引用的對象的類,而T
是已解析類,數組或接口的類型,則instanceof
確定是否 objectref
是T
的一個實例。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
本身也是對象。
【作者簡介】:
秦懷,公眾號【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。這個世界希望一切都很快,更快,但是我希望自己能走好每一步,寫好每一篇文章,期待和你們一起交流。
此文章僅代表自己(本菜鳥)學習積累記錄,或者學習筆記,如有侵權,請聯系作者核實刪除。人無完人,文章也一樣,文筆稚嫩,在下不才,勿噴,如果有錯誤之處,還望指出,感激不盡~