สวัสดี! วันนี้เราจะมาพูดถึงอินสแตนซ์ของโอเปอเรเตอร์ ดูตัวอย่างการใช้งานและสัมผัสบางจุดที่เกี่ยวข้องกับการทำงานของมัน :) ในระดับเริ่มต้นของ JavaRush คุณได้พบโอเปอเรเตอร์นี้แล้ว คุณจำได้ไหมว่าทำไมมันถึงจำเป็น? ถ้าไม่ก็ไม่เป็นไรเรามาจำไปด้วยกัน จำเป็นต้องใช้ตัวดำเนินการ instanceof เพื่อตรวจสอบว่าวัตถุที่อ้างอิงโดยตัวแปร X ถูกสร้างขึ้นจากคลาส Y บางคลาสหรือไม่ ฟังดูง่าย ทำไมเราถึงกลับมาที่หัวข้อนี้? ก่อนอื่น เพราะตอนนี้คุณคุ้นเคยกับกลไกการสืบทอดใน Java และหลักการ OOP อื่นๆ เป็นอย่างดีแล้ว หัวข้อของinstanceofจะมีความชัดเจนมากขึ้น และเราจะพิจารณากรณีการใช้งานขั้นสูงเพิ่มเติม ไป!
คุณคงจำได้ว่าตัวดำเนินการ instanceof คืนค่าเป็นจริงหากการทดสอบเป็นจริง หรือคืนค่าเท็จหากผลลัพธ์เป็นเท็จ ดังนั้นจึงมักพบในสภาวะการทดสอบประเภทต่างๆ (
ตัวอย่างเช่น คุณคิดว่าเช็คต่อไปนี้จะทำให้เกิดอะไร:
if…else
) เริ่มจากตัวอย่างที่ง่ายกว่านี้:
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof Integer);
}
}
คุณคิดว่าอะไรจะถูกส่งออกไปยังคอนโซล? ก็ชัดเจนที่นี่ :) วัตถุนั้นх
เป็นจำนวนเต็ม ดังนั้นผลลัพธ์จะเป็นจริง เอาต์พุตคอนโซล: จริง ลองตรวจสอบว่ามันเป็นของสตริงหรือไม่:
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof String);// error!
}
}
เราได้รับข้อผิดพลาด และให้ความสนใจ: คอมไพเลอร์ออกมันก่อนที่จะรันโค้ดด้วยซ้ำ! เขาเห็นทันทีว่าจำนวนเต็มและสตริงไม่สามารถแปลงเป็นค่าอื่นได้โดยอัตโนมัติ และไม่มีความสัมพันธ์แบบสืบทอด ดังนั้นวัตถุคลาส 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);
}
}
ผลลัพธ์: จริง เท็จ คำถามหลักที่ต้องตอบคือ 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 คอนโซลเอาท์พุตจะมีลักษณะดังนี้: Constructor ของคลาสพื้นฐาน Animal กำลังทำงานอยู่ ตัวแปรของคลาส Animal ได้รับการเตรียมใช้งานแล้วหรือยัง? มูลค่าปัจจุบันของตัวแปรคงที่ animalCount = 7700000 มูลค่าปัจจุบันของสมองในประเภทสัตว์ = ค่าเริ่มต้นของสมองในประเภทสัตว์ มูลค่าปัจจุบันของหัวใจในประเภทสัตว์ = ค่าเริ่มต้นของหัวใจในประเภทสัตว์ ตัวสร้างของประเภทฐาน สัตว์ ทำงานเสร็จแล้ว! ค่าปัจจุบันของสมอง = Brain ค่าปัจจุบันของหัวใจ = หัวใจ ตัวสร้างของคลาส Cat ได้เริ่มทำงานแล้ว (ตัวสร้างสัตว์ได้ถูกดำเนินการแล้ว) ค่าปัจจุบันของตัวแปรคงที่ catCount = 37 ค่าปัจจุบันของส่วนหาง = ค่าเริ่มต้นของส่วนท้ายใน คลาสแมว ค่าปัจจุบันของหาง = หาง จำตอนนี้ได้ไหม? :) ตัวสร้างคลาสพื้นฐาน (ถ้ามี) จะถูกเรียกก่อนเสมอเมื่อสร้างวัตถุใดๆ 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 ตรวจสอบที่มาของวัตถุ ไม่ใช่ตัวแปร ดังนั้นในตัวอย่างทั้งสองครั้งจะแสดงเป็น trueMaineCoon
ในคอนโซล : เรามีวัตถุประเภท โดยปกติแล้วมันถูกสร้างขึ้นตามคลาสMaineCoon
แต่ก็ขึ้นอยู่กับคลาสพาเรนต์Cat
ด้วย!
GO TO FULL VERSION