โค้ดยิม/จาวาบล็อก/สุ่ม/ลำดับของการกระทำระหว่างการสร้างวัตถุ
John Squirrels
ระดับ
San Francisco

ลำดับของการกระทำระหว่างการสร้างวัตถุ

เผยแพร่ในกลุ่ม
สวัสดี! บทเรียนวันนี้จะค่อนข้าง... เอ่อ... หลาย แง่มุม :) ในแง่ที่เราจะครอบคลุมหัวข้อที่หลากหลาย แต่ทั้งหมดจะเกี่ยวข้องกับกระบวนการสร้างวัตถุ ลำดับของการกระทำระหว่างการสร้างวัตถุ - 1เราจะวิเคราะห์ตั้งแต่ต้นจนจบ: วิธีเรียกคอนสตรัคเตอร์ วิธีและในฟิลด์คำสั่งใด (รวมถึงฟิลด์สแตติก) เริ่มต้นอย่างไร ฯลฯ ก่อนหน้านี้เราได้กล่าวถึงบางประเด็นที่กล่าวถึงในบทความ ดังนั้นคุณจึงสามารถมองข้าม วัสดุบน ตัวสร้าง คลาสพื้นฐาน ก่อนอื่น เรามานึกถึงวิธีการสร้างวัตถุกันก่อน คุณคงจำได้ดีว่ากระบวนการนี้มองจากมุมมองของนักพัฒนาอย่างไร เขาสร้างคลาส เขียนnewและทุกอย่างก็พร้อม :) ที่นี่เราจะพูดถึงสิ่งที่เกิดขึ้นภายในคอมพิวเตอร์และเครื่อง Java เมื่อเราเขียน ตัวอย่างเช่น:
Cat cat = new Cat();
เราเคยพูดถึงเรื่องนี้มาก่อนแล้ว แต่ในกรณีที่เราจะเตือนคุณ:
  • ขั้นแรกให้จัดสรรหน่วยความจำสำหรับจัดเก็บวัตถุ
  • ถัดไป เครื่อง Java สร้างการอ้างอิงถึงวัตถุ (ในกรณีของเรา การอ้างอิงคือ Cat cat)
  • สุดท้าย ตัวแปรจะเริ่มต้นและตัวสร้างถูกเรียก (เราจะดูรายละเอียดเพิ่มเติมเกี่ยวกับกระบวนการนี้)
นอกจากนี้ จากบทเรียนเกี่ยวกับวัฏจักรชีวิตของออบเจกต์คุณอาจจำได้ว่าออบเจกต์จะคงอยู่ตราบเท่าที่มีการอ้างอิงอย่างน้อยหนึ่งรายการ หากไม่เหลือวัตถุนั้นจะกลายเป็นเหยื่อของคนเก็บขยะ ลำดับของการกระทำระหว่างการสร้างวัตถุ - 2สองประเด็นแรกนี้ไม่ควรตั้งคำถามพิเศษใดๆ การจัดสรรหน่วยความจำเป็นกระบวนการง่ายๆ และมีเพียงสองผลลัพธ์ที่เป็นไปได้: หน่วยความจำมีหรือไม่มี :) และการสร้างลิงก์ก็ไม่ใช่เรื่องแปลก แต่จุดที่สามแสดงถึงการดำเนินการทั้งชุดที่ดำเนินการตามลำดับที่เข้มงวด ฉันไม่ชอบการยัดเยียดการทดสอบ แต่คุณต้องเข้าใจกระบวนการนี้อย่างดี และคุณต้องจำลำดับของการดำเนินการนี้. เมื่อเราพูดถึงกระบวนการสร้างวัตถุในบทเรียนก่อนหน้านี้ คุณยังไม่รู้อะไรเกี่ยวกับการสืบทอด ดังนั้นการอธิบายบางสิ่งจึงเป็นปัญหา ตอนนี้คุณรู้ค่อนข้างมากแล้ว และในที่สุดเราก็สามารถพิจารณาคำถามนี้ทั้งหมดได้ :) ดังนั้นจุดที่สามจึงบอกว่า " ในที่สุด ตัวแปรจะถูกเตรียมใช้งานและตัวสร้างถูกเรียก " แต่ทั้งหมดนี้เกิดขึ้นในลำดับใด เพื่อความเข้าใจที่ดีขึ้น ลองสร้างคลาสง่ายๆ สองคลาส — คลาสผู้ปกครองและคลาสย่อย:
public class Vehicle {

   public static int vehicleCounter = 0;

   private String description = "Vehicle";
   public Vehicle() {
   }

   public String getDescription() {
       return description;
   }
}

public class Truck extends Vehicle {

   private static int truckCounter = 0;

   private int yearOfManufacture;
   private String model;
   private int maxSpeed;

   public Truck(int yearOfManufacture, String model, int maxSpeed) {
       this.yearOfManufacture = yearOfManufacture;
       this.model = model;
       this.maxSpeed = maxSpeed;

       Vehicle.vehicleCounter++;
       truckCounter++;
   }
}
คลาส นี้Truckเป็นการนำรถบรรทุกมาใช้โดยมีช่องแสดงปี รุ่น และความเร็วสูงสุด ตอนนี้เราต้องการสร้างวัตถุดังกล่าว:
public class Main {

   public static void main(String[] args) throws IOException {

       Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
   }
}
สำหรับเครื่อง Java กระบวนการจะมีลักษณะดังนี้:
  1. สิ่งแรกที่เกิดขึ้นคือตัวแปรสแตติกของVehicleคลาสจะเริ่มต้น ใช่ ชั้นบอกว่าVehicleไม่ใช่ Truckตัวแปรสแตติกจะเริ่มต้นก่อนที่จะเรียกคอนสตรัคเตอร์ และจะเริ่มต้นในคลาสพาเรนต์ มาลองตรวจสอบสิ่งนี้กัน เราตั้งค่าvehicleCounterฟิลด์ในVehicleคลาสเท่ากับ 10 และพยายามแสดงทั้งในVehicleและTruckตัวสร้าง

    public class Vehicle {
    
       public static int vehicleCounter = 10;
       private String description = "Vehicle";
    
       public Vehicle() {
           System.out.println(vehicleCounter);
       }
    
       public String getDescription() {
           return description;
       }
    }
    
    public class Truck extends Vehicle {
    
       private static int truckCount = 0;
    
       private int yearOfManufacture;
       private String model;
       private int maxSpeed;
    
       public Truck(int yearOfManufacture, String model, int maxSpeed) {
           System.out.println(vehicleCounter);
           this.yearOfManufacture = yearOfManufacture;
           this.model = model;
           this.maxSpeed = maxSpeed;
    
           Vehicle.vehicleCounter++;
           truckCount++;
       }
    }

    เราจงใจใส่คำสั่ง println ที่จุดเริ่มต้นของTruckตัวสร้างเพื่อให้แน่ใจว่าฟิลด์ของรถบรรทุกยังไม่ได้เริ่มต้นเมื่อvehicleCounterแสดง

    และนี่คือผลลัพธ์:

    10
    10
  2. หลังจากเริ่มต้นตัวแปรสแตติกของคลาสพาเรนต์แล้ว ตัวแปรสแตติกของคลาสลูกจะถูกเตรียมใช้งาน ในกรณีของเรา นี่คือtruckCounterฟิลด์ของTruckคลาส

    ลองทำการทดลองอีกครั้งโดยเราจะพยายามแสดงค่าtruckCounterภายในTruckคอนสตรัคเตอร์ก่อนที่ฟิลด์อื่นๆ จะเริ่มต้น:

    public class Truck extends Vehicle {
    
       private static int truckCounter = 10;
    
       private int yearOfManufacture;
       private String model;
       private int maxSpeed;
    
       public Truck(int yearOfManufacture, String model, int maxSpeed) {
           System.out.println(truckCounter);
           this.yearOfManufacture = yearOfManufacture;
           this.model = model;
           this.maxSpeed = maxSpeed;
    
           Vehicle.vehicleCounter++;
           truckCounter++;
       }
    }

    อย่างที่คุณเห็น ค่า 10 ถูกกำหนดให้กับตัวแปรสแตติกของเราแล้วเมื่อTruckคอนสตรัคเตอร์เริ่มทำงาน

  3. ยังไม่ถึงเวลาสำหรับผู้สร้าง! การเริ่มต้นตัวแปรยังคงดำเนินต่อไป ตัวแปรที่ไม่คงที่ของคลาสพาเรนต์เริ่มต้นที่สาม อย่างที่คุณเห็น การสืบทอดทำให้กระบวนการสร้างวัตถุซับซ้อนขึ้นอย่างมาก แต่คุณทำอะไรไม่ได้เลย: คุณเพียงแค่ต้องจดจำบางสิ่งในการเขียนโปรแกรม :)

    ในการทดลอง เราสามารถกำหนดค่าเริ่มต้นให้กับdescriptionตัวแปรในVehicleคลาส แล้วเปลี่ยนค่านั้นในคอนสตรัคเตอร์

    public class Vehicle {
    
       public static int vehicleCounter = 10;
    
       private String description = "Initial value of the description field";
    
       public Vehicle() {
           System.out.println(description);
           description = "Vehicle";
           System.out.println(description);
       }
    
       public String getDescription() {
           return description;
       }
    }

    ลองใช้ main()วิธีการของเราเพื่อสร้างรถบรรทุก:

    public class Main {
    
       public static void main(String[] args) throws IOException {
    
           Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
       }
    }

    เราได้ผลลัพธ์ดังต่อไปนี้:

    Initial value of the description field
    Vehicle

    นี่เป็นการพิสูจน์ว่าเมื่อVehicleคอนสตรัคเตอร์เริ่มdescriptionฟิลด์ได้รับการกำหนดค่าแล้ว

  4. ในที่สุดก็ถึงเวลาสำหรับผู้สร้าง! แม่นยำยิ่งขึ้น ถึงเวลาแล้วสำหรับตัวสร้างคลาสพื้นฐาน มันถูกเรียกใช้ในขั้นตอนที่สี่ของกระบวนการสร้างวัตถุ

    นอกจากนี้ยังง่ายต่อการตรวจสอบ ลองส่งออกสองบรรทัดไปยังคอนโซล: บรรทัดหนึ่งภายในVehicleตัวสร้างคลาสพื้นฐาน และบรรทัดที่สองภายในTruckตัวสร้าง เราต้องแน่ใจว่าบรรทัดภายในVehicleปรากฏขึ้นก่อน:

    public Vehicle() {
    
       System.out.println("Hello from the Vehicle constructor!");
    }
    
    public Truck(int yearOfManufacture, String model, int maxSpeed) {
    
       System.out.println("Hello from the Truck constructor!");
       this.yearOfManufacture = yearOfManufacture;
       this.model = model;
       this.maxSpeed = maxSpeed;
    
       Vehicle.vehicleCounter++;
       truckCounter++;
    }

    เราจะใช้main()วิธีของเราและดูผลลัพธ์:

    Hello from the Vehicle constructor!
    Hello from the Truck constructor!

    ยอดเยี่ยม. แสดงว่าเราคิดไม่ผิด :) ไปกันต่อ

  5. ถึงเวลาเริ่มต้นฟิลด์ที่ไม่คงที่ของคลาสลูก นั่นคือTruckคลาส ของเรา ฟิลด์ทันทีภายในคลาสที่กำลังสร้างอินสแตนซ์จะไม่เริ่มต้นจนกว่าจะถึงขั้นตอนที่ห้า! น่าแปลกใจ แต่ก็จริง :) อีกครั้ง เราจะทำการตรวจสอบง่ายๆ — เช่นเดียวกับคลาสพาเรนต์: เราจะกำหนดค่าเริ่มต้นให้กับตัวแปรmaxSpeedและในTruckคอนสตรัคเตอร์ เราจะตรวจสอบว่าค่านั้นถูกกำหนดก่อนที่คอนสตรัคเตอร์จะเริ่มทำงาน:

    public class Truck extends Vehicle {
    
       private static int truckCounter = 10;
    
       private int yearOfManufacture;
       private String model;
       private int maxSpeed = 150;
    
       public Truck(int yearOfManufacture, String model, int maxSpeed) {
    
           System.out.println("Initial value of maxSpeed = " + this.maxSpeed);
           this.yearOfManufacture = yearOfManufacture;
           this.model = model;
           this.maxSpeed = maxSpeed;
    
           Vehicle.vehicleCounter++;
           truckCounter++;
       }
    }

    เอาต์พุตคอนโซล:

    Initial value of maxSpeed = 150

    อย่างที่คุณเห็น  เมื่อTruck คอนสตรัคเตอร์เริ่มmaxSpeed มีค่าเท่ากับ 150 แล้ว!

  6. คอนสตรัคเตอร์ของTruckคลาสลูกเรียกว่า

    และเมื่อถึงจุดนี้สุดท้ายแล้ว ตัวสร้างของคลาสที่เรากำลังสร้างอินสแตนซ์จะถูกเรียก!

    เฉพาะในขั้นตอนที่หกฟิลด์จะได้รับการกำหนดค่าที่เราส่งผ่านเป็นอาร์กิวเมนต์ไปยังรถบรรทุกของเรา

    อย่างที่คุณเห็น การ "สร้าง" รถบรรทุก ซึ่งก็คือกระบวนการสร้างวัตถุนั้นไม่ง่ายเลย แต่ดูเหมือนว่าเราได้แยกมันออกเป็นส่วนที่เล็กที่สุดแล้ว :)

ลำดับของการกระทำระหว่างการสร้างวัตถุ - 3 เหตุใดการทำความเข้าใจกระบวนการนี้จึงสำคัญมาก ลองนึกภาพว่าผลลัพธ์ของการสร้างวัตถุธรรมดาที่คาดไม่ถึงจะเป็นอย่างไรหากคุณไม่รู้ว่าเกิดอะไรขึ้น "ภายใต้ประทุน" :) ตอนนี้ได้เวลากลับไปที่หลักสูตรและทำงานบางอย่างให้เสร็จ! ขอให้โชคดี แล้วพบกันเร็ว ๆ นี้! :)
ความคิดเห็น
  • เป็นที่นิยม
  • ใหม่
  • เก่า
คุณต้องลงชื่อเข้าใช้เพื่อแสดงความคิดเห็น
หน้านี้ยังไม่มีความคิดเห็นใด ๆ