Java基礎-instanceof用法揭秘

2021-01-11 掌趣網絡

如何判斷是不是誰的誰?Java有一個 instanceof 操作符(關係操作符)可以做這件事。

public static void main(String[] args) {String s = "Hello World!";System.out.println(s instanceof String);}

列印出結果:

true

可是如果你的那個誰不存在呢?請看代碼:

public static void main(String[] args) {String s = null;System.out.println(s instanceof String);}

很多人都會異口同聲的說:

false

你答對了!

JSL-15.20.2 規定

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.註:在運行期,如果關係表達式不為空,並且類型轉換時不會拋出ClassCastException異常時,instanceof表達式返回結果為真,否則結果為假

牽線之亂點鴛鴦譜

如果沒有任何關係的兩個類使用 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.註:instanceof操作符的關係表達式操作數的類型必須是一個引用類型或者null類型,否則拋出編譯錯誤It is a compile-time error if the ReferenceType mentioned after the instanceof operator does not denote a reference type that is reifiable。註:如在instanceof操作符後面提及的引用類型表示的不是可具化(§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.註:如從關係表達式到引用類型的強制類型轉換將作為編譯時錯誤而拒絕,那麼 instanceof 關係表達式也就同樣地產生編譯時錯誤。這種情況下,instanceof 表達式的結果也永遠不會是真。

當然,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).註:我認為這意味著isInstance()主要用於在運行時處理類型反射的代碼中。特別是,我想說它的存在是為了處理,您可能事先不知道您想要檢查的類的類型(s)(儘管這些情況可能很少)的情況。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.註:一般來說,我想說,當您知道要提前檢查的類的類型時,應該首選使用instanceof。在不使用isInstance()的非常罕見的情況下,可以使用isInstance()

總結

回歸本源,instanceof 是 Java 中的二元運算符,左邊是對象,右邊是類;當對象是右邊類或子類所創建對象時,返回 true;否則,返回 false。

相關焦點

  • Java基礎學習:java中的基本數據類型
    二、案例用法 1、類型轉換 +=運算符是java語言規定的,編譯器會對它進行識別處理,因此可以正確編譯。
  • 打工人打工魂,打工的必會java調用python的幾種用法
    本文轉載自【微信公眾號:五角錢的程式設計師,ID:xianglin965】,經微信公眾號授權轉載,如需轉載與原文作者聯繫圖丨pexelsjava調用python的幾種用法(看這篇就夠了)在java類中直接執行python語句準備工作:創建maven工程,結構如下:到官網https://www.jython.org
  • Java程式設計師必備基礎:Java代碼是怎麼運行的?
    java源文件編譯為class字節碼 類加載器把字節碼加載到虛擬機的方法區。但是java是一門面向對象的高級語言,它不僅語法非常複雜,抽象程度也非常高,並不能直接運行在計算機硬體機器上。 Java虛擬機(Java Virtual Machine 簡稱JVM)是運行所有Java程序的抽象計算機,是Java語言的運行環境。
  • JAVA-二進位基礎
    十進位轉十六進位同理二、位運算優點:(1)特定情況下,計算方便,速度快,被支持面廣(2)如果用算數方法,速度慢,邏輯複雜2.1、按位與&兩位全為一,結果才為10&0=0;0&1=0;1&0=0;1&1=1;用法:(1)清零,如果想要將一個單元清零
  • JAVA map的用法/如何遍歷MAP
    第一步,,要引入它所在JAR—— 可以在JAVA類裡直接引入import java.util.*;  這樣until下的所有接口都可以調用,還有常用到的是List.整體測試方法:package zy.until;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set
  • 2020年Java基礎高頻面試題匯總
    深拷貝:被複製對象的所有變量都含有與原來的對象相同的值.而那些引用其他對象的變量將指向被複製過的新對象.而不再是原有的那些被引用的對象.換言之.深拷貝把要複製的對象所引用的對象都19、nal有哪些用法?
  • 跟我學java編程—Java邏輯運算符
    示例1:邏輯運算符在D盤Java目錄下,新建「LogicSample.java」文件。用記事本打開「LogicSample.java」文件,輸入以下代碼:代碼結構分析程序功能主要是演示邏輯運算符的用法。類似語句「bJudge = !
  • 饑荒聯機版表情代碼用法大揭秘
    今天小編給大家帶來了饑荒聯機版表情代碼用法,在饑荒最新版本中已經增加了表情代碼,我們可以通過輸入表情代碼讓人物做出不同的動作,感興趣的小夥伴一起來看看饑荒聯機版表情代碼用法吧! 首先我們來看看更新日誌原文: Add slash commands(emotes).
  • Java之this關鍵字的用法
    給位小夥伴們大家好,在之前的文章中,小編有講過super關鍵字的用法Java之super關鍵字的用法。這次小編要介紹的是在Java當中this關鍵字的用法。具體如下:1.在本類的成員方法中,訪問本類的成員變量。
  • Java NIO 基礎知識
    在 Java 領域,一般性的文件操作確實只需要和 java.io 包打交道就可以了,尤其對於寫業務代碼的程式設計師來說。不過,當你寫了兩三年代碼後,你的業務代碼可能已經寫得很溜了,蒙著眼睛也能寫增刪改查了。這個時候,也許你會想要開始了解更多的底層內容,包括並發、JVM、分布式系統、各個開源框架源碼實現等,處於這個階段的程式設計師會開始認識到 NIO 的用處,因為系統間通訊無處不在。
  • 零基礎java入門教程函數function實例化格式案例void返回值說明
    java基礎自學入門:函數:定義在類中的具有特定功能的一段獨立小程序有時候我們函數也稱為方法,平時我們聽到的函數也就是方法,方法也是函數,每個人的叫法不同,所以這裡要切記。老程式設計師別露餡喲。傳遞給形參的具體數值;return:用於結束函數;返回值:該值會返回給調用者;java
  • Mars-java 2.2.2 發布,不需要容器的 Java Web 開發框架
    本次更新如下: 取消了MarsMapping註解,Controller裡的所有public方法會自動映射成一個http接口,默認請求方式為get 新增了RequestMethod註解,用來指定http接口的請求方式(不加默認為get) 將Resource註解換成了MarsWrite註解,用法保持不變
  • Java 生成隨機數的 5 種方式,你知道幾種?
    Java生成隨機數的幾種高級用法,這篇推薦看一下。 因此 方法是線程安全的。 什麼情況下隨機數的生成線程不安全: 線程1在第一次調用 時產生一個生成器 ,使用當前時間作為種子。
  • 開發崗位這麼多,為什麼選Java?你學Java了嗎-開課吧
    其他程式語言與Java相比,Java語法相對簡單,並且是很多計算機語言的基礎。提到C++語言,很多人發現在使用過程中最容易出現的錯誤就是內存管理,而java有自動垃圾回收器,不用擔心內存。java工程師工資一般多少?java自學容易嗎?
  • JAVA專業術語面試100問
    4、java有哪些基本數據類型?5、數組有沒有length()方法?String有沒有length()方法?數組沒有length()方法,它有length屬性。String有length()方法。是線程不安全的)StringBuffer:適用多線程下在字符緩衝區進行大量操作的情況(一般很少)(是線程安全的)首先說運行速度,或者說是執行速度,在這方面運行速度快慢為:StringBuilder > StringBuffer > String12、Java集合框架的基礎接口有哪些
  • Java之super關鍵字的用法
    各為小夥伴們大家好,這次小編要介紹的是Java當中super關鍵字的用法,在上面的文章中小編有講過,super關鍵字是用來調用父類之間的成員變量和成員方法。現在小編來總結一下super關鍵字的用法。具體如下:1.在子類的成員方法中,訪問父類的成員變量。
  • Mars-java 2.1.5 發布 - OSCHINA - 中文開源技術交流社區
    Mars-java 2.1.5 主要變更如下: 新增了MarsValue註解,可以將yml文件裡的節點值注入到bean的屬性裡 新增了MarsTimer註解,一行註解即可完成定時任務 配置文件可隔離
  • 英語基礎詞彙及解析有哪些用法呢?
    下面一起看一下英語基礎詞彙及解析有哪些用法呢?1、英語基礎詞彙及解析——dress用法小議:用作名詞,表示「衣服」,注意兩種用法:用作可數名詞,主要指婦女穿的連衣裙或上下連身的女裝,也可指小孩穿的衣服,但不指男人穿的衣服。
  • Java基礎,類的繼承,粗略的理解希望對大家有所幫助!
    Java基礎:繼承讀者老爺們大家好,今天圖圖帶大家了解一下java基礎裡的繼承。首先確定一下我們今天的學習的三個目標。第一個是類的繼承;第二個是訪問控制權限;第三個方法重寫(覆蓋)override。好滴,話不多說,讓我們快樂的投身知識的海洋裡吧!
  • java軟體工程師的這些要求你有嗎?
    如今java是IT界數一數二的語言,許多程式設計師都想要成為java軟體工程師,那大家知道企業對於java軟體工程師的技術要求有哪些嗎?java軟體工程師的技術要求一.java技術要求:1.具有良好的Java語言基礎,面向對象編程基礎2.熟悉Struts、Hibernate、Spring等主流技術框架3.熟悉XML解析、Excel導出、文件上傳、發送E-mail等常見業務的實現二.資料庫技術要求1.掌握、運用SQLServer