CodeGym /จาวาบล็อก /สุ่ม /อินสแตนซ์ Java ของตัวดำเนินการ
John Squirrels
ระดับ
San Francisco

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

เผยแพร่ในกลุ่ม
สวัสดี! วันนี้เราจะพูดถึง ตัวดำเนินการ instanceofพิจารณาตัวอย่างวิธีการใช้งาน และสัมผัสกับบางแง่มุมของวิธีการทำงาน :) คุณเคยพบตัวดำเนินการนี้ในระดับต้นๆ ของ CodeGym แล้ว คุณจำได้ไหมว่าทำไมเราต้องการมัน? ถ้าไม่ก็ไม่ต้องกังวล มารำลึกความหลังกัน จำเป็นต้องใช้ ตัว ดำเนินการ อินสแตนซ์เพื่อตรวจสอบว่าวัตถุที่อ้างอิงโดย ตัวแปร Xนั้นถูกสร้างขึ้นตามคลาสY บางตัวหรือไม่ ฟังดูง่าย ทำไมเรากลับมาที่หัวข้อนี้? ก่อนอื่น เนื่องจากตอนนี้คุณคุ้นเคยกับกลไกการสืบทอดของ Java และหลักการอื่นๆ ของ OOP เป็นอย่างดีแล้ว ตอนนี้ ตัว ดำเนินการ อินสแตนซ์จะมีความชัดเจนมากขึ้น และเราจะดูตัวอย่างขั้นสูงเพิ่มเติมเกี่ยวกับวิธีการใช้ ไปกันเถอะ!วิธีการทำงานของตัวดำเนินการอินสแตนซ์ - 1คุณอาจจำได้ว่า ตัวดำเนินการ ของอินสแตนซ์จะส่งกลับค่าจริงหากการตรวจสอบประเมินค่าเป็นจริง หรือเป็นเท็จหากนิพจน์เป็นเท็จ ดังนั้น มักจะเกิดขึ้นในนิพจน์เงื่อนไขทุกประเภท ( if…else ) เริ่มจากตัวอย่างง่ายๆ กันก่อน:

public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof Integer);
   }
}
คุณคิดว่าจะแสดงอะไรบนคอนโซล? มันชัดเจนที่นี่ :) วัตถุ xเป็นจำนวนเต็ม ดังนั้นผลลัพธ์จะเป็นจริง เอาต์พุตคอนโซล: True มาลองตรวจสอบว่าเป็นString :

public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof String); // Error!
   }
}
เราได้รับข้อผิดพลาด และให้ความสนใจ: คอมไพเลอร์สร้างข้อผิดพลาดก่อนรันโค้ด! เห็นได้ทันทีว่าจำนวนเต็มและสตริงไม่สามารถแปลงให้กันโดยอัตโนมัติและไม่เกี่ยวข้องกันผ่านการสืบทอด ดังนั้น วัตถุจำนวนเต็มจะไม่ ถูกสร้างตามString สิ่งนี้สะดวกและช่วยหลีกเลี่ยงข้อผิดพลาดรันไทม์แปลก ๆ ดังนั้นคอมไพเลอร์จึงช่วยเราที่นี่ :) ตอนนี้ลองพิจารณาตัวอย่างที่ยากขึ้น เนื่องจากเรากล่าวถึงการสืบทอด มาทำงานกับระบบคลาสย่อยต่อไปนี้:

public class Animal {

}

public class Cat extends Animal {

}

public class MaineCoon extends Cat {

}
เรารู้แล้วว่าอินสแตนซ์มีพฤติกรรมอย่างไรเมื่อเราตรวจสอบว่าอ็อบเจกต์เป็นอินสแตนซ์ของคลาสหรือไม่ แต่จะเกิดอะไรขึ้นหากเราพิจารณาความสัมพันธ์ระหว่างพ่อแม่และลูก ตัวอย่างเช่น คุณคิดว่านิพจน์เหล่านี้จะให้ผลลัพธ์อย่างไร:

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);

   }
}
ผลลัพธ์: จริง เท็จ คำถามหลักที่ต้องตอบคืออินสแตนซ์ตีความ 'วัตถุที่สร้างขึ้นตามคลาส' ได้อย่างไร ' cat instanceof Animal ' ประเมินเป็นtrueแต่แน่นอนว่าเราสามารถหาข้อผิดพลาดจากถ้อยคำนั้นได้ เหตุใดวัตถุ Catจึงถูกสร้างขึ้นตามคลาสAnimal มันไม่ได้สร้างตามคลาสของตัวเองอย่างเดียวเหรอ? คำตอบนั้นง่ายมาก และคุณอาจคิดไว้แล้ว จำลำดับที่คอนสตรัคเตอร์ถูกเรียกและตัวแปรถูกเตรียมใช้งานเมื่อสร้างอ็อบเจกต์ เราได้กล่าวถึงหัวข้อนี้แล้วในบทความเกี่ยวกับตัวสร้างคลาส นี่คือตัวอย่างจากบทเรียนนั้น:

public class Animal {

   String brain = "Initial value of brain in the Animal class";
   String heart = "Initial value of heart in the Animal class";

   public static int animalCount = 7700000;

   public Animal(String brain, String heart) {
       System.out.println("Animal base class constructor is running");
       System.out.println("Have the variables of the Animal class already been initialized?");
       System.out.println("Current value of static variable animalCount = " + animalCount);
       System.out.println("Current value of brain in the Animal class = " + this.brain);
       System.out.println("Current value of heart in the Animal class = " + this.heart);
       System.out.println("Have the variables of the Cat class already been initialized?");
       System.out.println("Current value of static variable catCount = " + Cat.catCount);

       this.brain = brain;
       this.heart = heart;
       System.out.println("Animal base class constructor is done!");
       System.out.println("Current value of brain = " + this.brain);
       System.out.println("Current value of heart = " + this.heart);
   }
}

public class Cat extends Animal {

   String tail = "Initial value of tail in the Cat class";

   static int catCount = 37;

   public Cat(String brain, String heart, String tail) {
       super(brain, heart);
       System.out.println("The Cat class constructor has started (The Animal constructor already finished)");
       System.out.println("Current value of static variable catCount = " + catCount);
       System.out.println("Current value of tail = " + this.tail);
       this.tail = tail;
       System.out.println("Current value of tail = " + this.tail);
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Brain", "Heart", "Tail");
   }
}
และถ้าคุณเรียกใช้ใน IDE เอาต์พุตของคอนโซลจะมีลักษณะดังนี้: ตัวสร้างคลาสฐานสัตว์กำลังทำงาน มีการเริ่มต้นตัวแปรของคลาสสัตว์แล้วหรือยัง ค่าปัจจุบันของตัวแปรสแตติก animalCount = 7700000 ค่าปัจจุบันของสมองในคลาสสัตว์ = ค่าเริ่มต้นของสมองในคลาสสัตว์ ค่าปัจจุบันของหัวใจในคลาสสัตว์ = ค่าเริ่มต้นของหัวใจในคลาสสัตว์ มีตัวแปรของคลาสแมวอยู่แล้ว ได้รับการเริ่มต้น? ค่าปัจจุบันของตัวแปรสแตติก catCount = 37 ตัวสร้างคลาสฐานสัตว์เสร็จแล้ว! ค่าปัจจุบันของสมอง = สมอง ค่าปัจจุบันของหัวใจ = หัวใจ ตัวสร้างคลาส cat ได้เริ่มต้นขึ้น (ตัวสร้างสัตว์เสร็จสิ้นแล้ว) ค่าปัจจุบันของตัวแปรคงที่ catCount = 37 ค่าปัจจุบันของหาง = ค่าเริ่มต้นของหางในคลาส Cat ค่าปัจจุบันของหาง = หาง ตอนนี้คุณจำได้ไหม :) คอนสตรัคเตอร์ของคลาสพื้นฐาน หากมีคลาสพื้นฐาน จะถูกเรียกเป็นอันดับแรกเสมอเมื่อสร้างวัตถุ ตัว ดำเนินการ อินสแตนซ์ได้รับคำแนะนำจากหลักการนี้เมื่อพยายามระบุว่า วัตถุ Aถูกสร้างขึ้นตามคลาสB หรือไม่ หากมีการเรียกใช้ตัวสร้างคลาสพื้นฐานก็ไม่ต้องสงสัยเลย ด้วยการตรวจสอบครั้งที่สอง ทุกอย่างจะง่ายขึ้น:

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 อย่างไรก็ตามทำไมมันถึงใช้งานได้? เราสามารถทำอย่างนั้นได้ใช่ไหม? ใช่เราทำได้ ท้ายที่สุด MaineCoon ทุกตัวก็เป็นแมว หากยังไม่ชัดเจน โปรดจำตัวอย่างการขยายประเภทดั้งเดิม:

public class Main {

   public static void main(String[] args) {

       long x = 1024;

   }
}
ตัวเลข1024นั้นสั้น : มันพอดีกับ ตัวแปร ยาว ได้อย่างง่ายดาย เนื่องจากมีไบต์เพียงพอที่จะรองรับ (จำตัวอย่างกับตุ๊กตาได้ไหม) สามารถกำหนดอ็อบเจ็กต์ลูกหลานให้กับตัวแปรบรรพบุรุษได้เสมอ สำหรับตอนนี้ จำไว้แค่นี้ แล้วในบทเรียนต่อๆ ไป เราจะวิเคราะห์ว่ามันทำงานอย่างไร ตัวอย่างของเราให้ผลลัพธ์อะไร

Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
จะตรวจสอบอินสแตนซ์ ของอะไร ตัวแปรCatของเรา หรือ วัตถุMaineCoon ของเรา คำตอบคือคำถามนี้ง่ายมาก คุณเพียงแค่ต้องอ่านคำจำกัดความของตัวดำเนินการอีกครั้ง: จำเป็นต้องใช้ตัวดำเนินการ อินสแตนซ์เพื่อตรวจสอบว่าวัตถุที่อ้างอิงโดย ตัวแปร Xถูกสร้างขึ้นตามคลาสY บางตัวหรือไม่ ตัว ดำเนินการอินส แตนซ์ทดสอบที่มาของวัตถุ ไม่ใช่ประเภทตัวแปร ดังนั้น ในตัวอย่างนี้ โปรแกรมของเราจะแสดงเป็น จริงในทั้งสองกรณี: เรามีวัตถุMaineCoon เห็นได้ชัดว่ามันถูกสร้างขึ้นตาม คลาส MaineCoonแต่มันถูกสร้างขึ้นจากCatชั้นผู้ปกครองด้วย!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION