JavaRush /จาวาบล็อก /Random-TH /อินสแตนซ์ของตัวดำเนินการใน Java

อินสแตนซ์ของตัวดำเนินการใน Java

เผยแพร่ในกลุ่ม
สวัสดี! วันนี้เราจะมาพูดถึงอินสแตนซ์ของโอเปอเรเตอร์ ดูตัวอย่างการใช้งานและสัมผัสบางจุดที่เกี่ยวข้องกับการทำงานของมัน :) ในระดับเริ่มต้นของ JavaRush คุณได้พบโอเปอเรเตอร์นี้แล้ว คุณจำได้ไหมว่าทำไมมันถึงจำเป็น? ถ้าไม่ก็ไม่เป็นไรเรามาจำไปด้วยกัน จำเป็นต้องใช้ตัวดำเนินการ instanceof เพื่อตรวจสอบว่าวัตถุที่อ้างอิงโดยตัวแปร X ถูกสร้างขึ้นจากคลาส Y บางคลาสหรือไม่ ฟังดูง่าย ทำไมเราถึงกลับมาที่หัวข้อนี้? ก่อนอื่น เพราะตอนนี้คุณคุ้นเคยกับกลไกการสืบทอดใน Java และหลักการ OOP อื่นๆ เป็นอย่างดีแล้ว หัวข้อของinstanceofจะมีความชัดเจนมากขึ้น และเราจะพิจารณากรณีการใช้งานขั้นสูงเพิ่มเติม ไป! ตัวดำเนินการอินสแตนซ์ทำงานอย่างไร - 1คุณคงจำได้ว่าตัวดำเนินการ 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 มีพฤติกรรมอย่างไรเมื่อเราตรวจสอบว่าอ็อบเจ็กต์อยู่ในคลาสในสถานการณ์ปกติหรือไม่ แต่จะเกิดอะไรขึ้นถ้าเราเพิ่มความสัมพันธ์ระหว่างพ่อแม่และลูกที่นี่ ตัวดำเนินการอินสแตนซ์ทำงานอย่างไร - 2 ตัวอย่างเช่น คุณคิดว่าเช็คต่อไปนี้จะทำให้เกิดอะไร:
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ด้วย!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION