你好!今天我們將討論instanceof運算符,看一下它的使用範例,並討論一些與其操作相關的要點:) 在JavaRush的早期階段,您已經遇到過這個運算符。你還記得為什麼需要它嗎?如果沒有,也沒關係,我們一起記得。需要使用instanceof運算子來檢查變數X引用的物件是否是從某個類別Y創建的。聽起來很簡單。為什麼我們又回到這個話題?首先,因為現在你已經熟悉了Java中的繼承機制和其他OOP原理。instanceof的主題將會更加清晰,我們將研究更進階的用例。去!您可能還記得,如果測試為真,則instanceof 運算子傳回true ;如果結果為false ,則傳回 false。因此,它最常見於各種類型的測試條件 (
if…else
)。讓我們從更簡單的例子開始:
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof Integer);
}
}
你認為控制台會輸出什麼?嗯,這很明顯:) 該物件х
是一個 Integer,所以結果將為true。控制台輸出:true 讓我們嘗試檢查它是否屬於字串:
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof String);// error!
}
}
我們收到一個錯誤。請注意:編譯器甚至在程式碼執行之前就發出了它!他立刻看到Integer和String不能自動互相轉換,也不具有繼承關係。因此,不會從 String 建立 Integer 類別物件。這很方便,有助於避免在程式執行期間出現奇怪的錯誤,因此編譯器在這裡幫助了我們:) 現在讓我們嘗試看看更複雜的範例。既然我們提到了繼承,那麼讓我們使用這個小型類別系統:
public class Animal {
}
public class Cat extends Animal {
}
public class MaineCoon extends Cat {
}
我們已經知道正常情況下檢查一個物件是否屬於某個類別時instanceof的行為如何,但是如果我們在這裡添加父子關係會發生什麼? 例如,您認為以下檢查會產生什麼結果:
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat instanceof Animal);
System.out.println(cat instanceof MaineCoon);
}
}
輸出:true false 需要回答的主要問題是,instanceof 究竟如何破解「基於類別創建的物件」的概念?結果,我們得到了它Сat instanceof Animal == true
,但人們可能會對這樣的表達提出錯誤。為什麼這個物件是Cat
基於類別創建的Animal
?不是只是根據自己的類別創建的嗎?答案很簡單,您可能已經想到了。記住創建物件時呼叫建構函數和初始化變數的順序。我們已經在有關類別構造函數的文章中討論了這個主題。這是該講座中的一個例子:
public class Animal {
String brain = "The initial value of brain in the Animal class";
String heart = "The initial value of heart in the Animal class";
public static int animalCount = 7700000;
public Animal(String brain, String heart) {
System.out.println("The constructor of the Animal base class is being executed");
System.out.println("Have the variables of the Animal class already been initialized?");
System.out.println("The current value of the static variable animalCount = " + animalCount);
System.out.println("Current value of brain in class Animal = " + this.brain);
System.out.println("Current value of heart in class Animal = " + this.heart);
this.brain = brain;
this.heart = heart;
System.out.println("Animal base class constructor completed!");
System.out.println("Current value of brain = " + this.brain);
System.out.println("Current value of heart = " + this.heart);
}
}
class Cat extends Animal {
String tail = "The initial value of tail in the Cat class";
static int catsCount = 37;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
System.out.println("The constructor of the Cat class has started (the Animal constructor has already been executed)");
System.out.println("The current value of the static variable catsCount = " + catsCount);
System.out.println("Current value tail = " + this.tail);
this.tail = tail;
System.out.println("Current value tail = " + this.tail);
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
如果你在 IDE 中運行它,控制台輸出將如下所示: The constructor of the base class Animal is running. Have the Variables of the Animal class have beeninitialized? 靜態變數animalCount的目前值 = 7700000 Animal類別中brain的目前值 = Animal類別中brain的初始值 Animal類別中heart的目前值 = Animal類別中heart的初始值 Animal類別基底類別的建構子已經完成了它的工作!Brain 的目前值 = Brain Heart 的目前值 = Heart Cat 類別的建構子已經開始工作(Animal 建構函式已經執行完畢) 靜態變數 catsCount 的目前值 = 37 tail 的目前值 = 中 tail 的初始值Cat 類別tail 目前值= Tail 現在你還記得嗎?:) 建立任何物件時,請務必先呼叫基底類別建構函式(如果有)。Instanceof 在嘗試確定物件是否是А
從類別建立時遵循此原則Б
。如果基底類別的建構子被調用,那麼就沒有疑問了。透過第二次檢查,一切都變得更簡單:
System.out.println(cat instanceof MaineCoon);
MaineCoon
創建時沒有呼叫 建構函數Cat
,這是合乎邏輯的。畢竟,MaineCoon
他是後人Cat
,不是祖先。但Cat
它不是一個模板。好吧,這看起來很清楚。如果我們這樣做會發生什麼:
public class Main {
public static void main(String[] args) {
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
}
}
嗯...這更複雜。讓我們試著推理一下。我們有一個類型的變量Cat
,並且為它分配了一個類型的物件MaineCoon
。順便問一下,為什麼這會起作用?是否有可能做到這一點?能。畢竟,任何緬因貓都是貓。如果還不完全清楚,請記住原始類型擴充的範例:
public class Main {
public static void main(String[] args) {
long x = 1024;
}
}
數字1024很短:它很容易適合long變量,因為位元組數足夠了(還記得嵌套娃娃的例子嗎?)。子物件始終可以分配給祖先變數。現在記住這一點,在接下來的講座中我們將進一步分析這個過程。那我們的例子會產生什麼結果呢?
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
instanceof 將檢查什麼:我們的類別變數Cat
還是我們的類別物件MaineCoon
?其實,這個問題的答案很簡單。你只需要再次閱讀我們的運算子的定義:需要instanceof運算子來檢查變數引用的物件是否是X
基於某個類別創建的Y
。 instanceof 運算子檢查物件的來源,而不是變數。 因此,在範例中,兩次都會在控制台中顯示true:我們有一個類型為 的物件MaineCoon
。當然,它是基於類別創建的MaineCoon
,但也是基於父類別創建的Cat
!
GO TO FULL VERSION