背景故事html
《曾經最美》是朱銘捷演唱的一首歌曲,由陳佳明填詞,葉良俊譜曲,是電視劇《水晶之戀》的主題曲。歌曲時長4分28秒。 歌曲歌詞:java
牽線之牛刀小試express
如何判斷是否是誰的誰?java有一個instanceof操做符(關係操做符)能夠作這件事。oracle
public static void main(String[] args) { String s = "Hello World!"; System.out.println(s instanceof String); }
打印出結果truethis
但是若是你的哪一個誰不存在呢?請看代碼:atom
public static void main(String[] args) { String s = null; System.out.println(s instanceof String); }
不少人都會異口同聲的說spa
falsecode
你答對了。htm
JSL-15.20.2規定blog
At run time, the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast to the ReferenceType without raising a ClassCastException. Otherwise the result is false.
牽線之亂點鴛鴦譜
若是沒有任何關係的兩個類使用instanceof會如何?
class Point { int x, y; } class Element { int atomicNumber; } public class InstanceofTest { public static void main(String[] args) { Point p = new Point(); Element e = new Element(); if (e instanceof Point) { System.out.println("匹配成功!"); }else { System.out.println("匹配不成功"); } } }
很多人會說:「匹配不成功」
抱歉,你又掉進坑裏了,這個會報編譯錯誤
JSL-15.20.2規定
The type of the RelationalExpression operand of the instanceof operator must be a reference type or the null type, or a compile-time error occurs.
It is a compile-time error if the ReferenceType mentioned after the instanceof operator does not denote a reference type that is reifiable (§4.7).
If a cast of the RelationalExpression to the ReferenceType would be rejected as a compile-time error (§15.16), then the instanceof relational expression likewise produces a compile-time error. In such a situation, the result of the instanceof expression could never be true.
固然,cast也會是編譯錯誤
class Point { int x, y; } class Element { int atomicNumber; } public class InstanceofTest { public static void main(String[] args) { Point p = new Point(); Element e = new Element(); p = (Point)e; // compile-time error } }
牽線之暗藏玄機
編譯器並非萬能的,並不能檢測出全部問題,看下面:
class Point { int x, y; } class Element { int atomicNumber; } public class InstanceofTest { public static void main(String[] args) { Point p = new Point(); //Element e = new Element(); p = (Point) new Object(); System.out.println(p instanceof Point); } }
猛一看,沒事問題,編譯也沒有問題,但是運行時報錯
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to Point
上面的程序展現了當要被轉型的表達式的靜態類型是轉型類型的超類時,轉型操做符的行爲。與instanceof 操做相同,若是在一個轉型操做中的兩種類型都是類,那麼其中一個必須是另外一個的子類型。儘管對咱們來講,這個轉
型很顯然會失敗,可是類型系統尚未強大到可以洞悉表達式new Object()的運行期類型不多是Point的一個子類型。所以,該程序將在運行期拋出ClassCastException 異常。
牽線之競爭激烈
關係操做符instanceof可不是市場上惟一的選擇,另一個背靠大山的傢伙要注意了
Class 的方法
booleanisInstance(Object obj)
Determines if the specified Object is assignment-compatible with the object represented by this Class.
那麼何時該用instanceof 何時該用isInstance呢
個人理解是
instanceof偏向於比較class之間
isInstance偏向於比較instance和class之間
stackoverflow也有此問題的解答:
I take that to mean that isInstance() is primarily intended for use in code dealing with type reflection at runtime. In particular, I would say that it exists to handle cases where you might not know in advance the type(s) of class(es) that you want to check for membership of in advance (rare though those cases probably are).
For instance, you can use it to write a method that checks to see if two arbitrarily typed objects are assignment-compatible, like:
public boolean areObjectsAssignable(Object left, Object right) { return left.getClass().isInstance(right); }
In general, I'd say that using instanceof should be preferred whenever you know the kind of class you want to check against in advance. In those very rare cases where you do not, use isInstance() instead.
參考資料
【1】https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.20.2
【2】java解惑
【3】https://stackoverflow.com/questions/8692214/when-to-use-class-isinstance-when-to-use-instanceof-operator