instanceof運算符用法
運算符是雙目運算符,左面的操作元是一個對象實例,右面是一個類.當
左面的對象是右面的類創建的對象時,該運算符運算的結果是true,否則是false
說明:
(1).一個類的實例包括本身的實例,以及所有直接或間接子類的實例
(2).instanceof左邊操作元顯式聲明的類型與右邊操作元必須是同種類或有繼承關系,
即位於繼承樹的同一個分支上,否則會編譯出錯
double obj=1; if(obj instanceof Double){ System.out.println("true"); }
報 "Incompatible conditional operand types double and Double" 錯誤
obj 必須是對象的實例。不能是基礎數據類型。
String obj=1.0+""; if(obj instanceof Double){ System.out.println("true"); }
報 "Incompatible conditional operand types String and Double" 錯誤
String 和 Double 不是位於繼承樹的同一個分支上。
if(null instanceof Object){ System.out.println("true"); }else{ System.out.println("false"); } String obj=null; if(obj instanceof Object){ System.out.println("true"); }else{ System.out.println("false"); }
打印都為 false. null用操作符instanceof測試任何類型時都是返回false的。
if(obj instanceof null){ System.out.println("true"); }else{ System.out.println("false"); }
編譯出錯。報"Syntax error on token "null", invalid ReferenceType" 錯誤。
public class Test { public static void main(String[] args){ System.out.println(new Student() instanceof String); //compile time error System.out.println(new Student() instanceof Exception); //compile time error System.out.println(new Student() instanceof Object); //compilation and output true System.out.println(new Student() instanceof List); //compilation and output false System.out.println(new Student() instanceof List<?>); //compilation and output false System.out.println(new Student() instanceof List<String>); //compile time error
System.out.println(new Student() instanceof List<Object>); //compile time error System.out.println(new String() instanceof List); //compile time error System.out.println(new String() instanceof List<?>); //compile time error System.out.println(null instanceof Object); //compilation and output false } } class Student{ }
看到上面的測試結果可能會有這樣那樣的疑惑,為什么Student對象測試String的時候是編譯錯誤,而測試List的時候又能夠通過(難道是instanceof對接口在編譯時不作檢查呢,還是由於List類型本身在編譯時不確定具體類型導致的),但是后面你又會發現如果是List<String>的時候編譯就不通過了(看來前面的猜測是錯誤的,他對接口是要做檢查的),可是往后面看,你又會納悶String測試List還是List<?>的時候,直接在編譯期就報錯了,這跟Student對象測試List和List<?>的結果大不同,可能此時你有點相當不解了。我們這個時候翻看java對instanceof操作符的說明時,發現instanceof的這些表現都是跟cast操作符是有點關系的,就是說當我們在instanceof方法時,編譯器會檢查這個對象能夠cast到右邊的類型,如果不能cast則直接報錯,如果不能確定類型,則通過編譯,具體看運行時定。
這里可能還有一個疑惑,我們Student已經確定類型了啊,List類型也是確定的啊,為什么能夠編譯通過呢,而String卻不行呢(難道是自己定義的類和系統定義的類在編譯處理上有不同),這里java沒有做特別的說明,但是我想可能是因為final關鍵字的區別造成的,我們發現不論String、Integer、Long等都是最終類,他們的處理類似於編譯器對常量的處理,因為編譯器知道這個類在運行期間是不會有改變的,故而編譯器在編譯期間認為他自己能夠確定這個類的最終類型。而對於自己定義的類呢(我試過系統的非最終類Hashtable、HashMap等,測試和我們自定義的類的結果一樣,可以通過編譯),由於不是最終類,可能編譯器認為他可能在運行期間會有改變的可能,故而不把他作最為確定的類型處理,故而可以通過編譯。其實當我們在自定義的類前面加上final關鍵字的時候,其表現就跟String、Integer、Long這些最終類測試instanceof表現的一樣了。