คำนำ
ใน Java วัตถุจะต้องเริ่มต้นอย่างถูกต้องก่อนที่จะสามารถใช้งานได้ซึ่งกำหนดโดยข้อกำหนด Java เมื่อเร็ว ๆ นี้ฉันค้นพบคำถามที่น่าสนใจและคำตอบสำหรับคำถามนี้หลอกตาของฉันได้อย่างรวดเร็วก่อน ลองดูที่สามหมวดหมู่นี้:
แพ็คเกจ com.ds.test; คลาสสาธารณะ Upper {String upperstring; สาธารณะบน () {initializer.initialize (นี่); - แพ็คเกจ com.ds.test; คลาสสาธารณะที่ต่ำกว่าขยาย {string lowerstring = null; สาธารณะล่าง () {super (); System.out.println ("Upper:" + Upperstring); System.out.println ("ต่ำกว่า:" + LowerString); } โมฆะคงที่สาธารณะหลัก (สตริงสุดท้าย [] args) {new lower (); - แพ็คเกจ com.ds.test; คลาสสาธารณะ initializer {โมฆะคงที่เริ่มต้น (anupper บนสุดท้าย) {ถ้า (anupper อินสแตนซ์ที่ต่ำกว่า) {ล่างล่าง = (ล่าง) anupper; ล่าง. lowerString = "ต่ำกว่า"; } anupper.upperstring = "UpperInited"; - เอาต์พุตใดที่สามารถรับได้โดยการเรียกใช้ชั้น Lower ? ในตัวอย่างที่น้อยที่สุดนี้สถานการณ์ทั้งหมดสามารถมองเห็นได้ง่ายขึ้น แต่สถานการณ์นี้เกิดขึ้นในความเป็นจริงและจะมีรหัสจำนวนมากที่ทำให้เสียสมาธิ
อย่างไรก็ตามผลลัพธ์ก็เป็นเช่นนี้:
Upper: Upperinitedlower: Null;
แม้ว่าประเภท String จะใช้ในตัวอย่างขนาดเล็กโค้ดจริงของคลาส Initializer มีวัตถุตัวแทนสำหรับการลงทะเบียนซึ่งเหมือนกับฟังก์ชั่นของคลาส Lower - อย่างน้อยคลาส Lower คือความตั้งใจ แต่ด้วยเหตุผลบางอย่างมันไม่ได้ผลเมื่อเรียกใช้แอปพลิเคชัน แต่จะใช้เส้นทางเริ่มต้นและวัตถุตัวแทนไม่ได้ตั้งค่า (NULL)
ตอนนี้เปลี่ยนรหัส Lower เล็กน้อย:
แพ็คเกจ com.ds.test; ระดับสาธารณะที่ต่ำกว่าขยาย {string lowerstring; สาธารณะล่าง () {super (); System.out.println ("Upper:" + Upperstring); System.out.println ("ต่ำกว่า:" + LowerString); } โมฆะคงที่สาธารณะหลัก (สตริงสุดท้าย [] args) {new lower (); -เอาต์พุตตอนนี้มีลักษณะเช่นนี้:
Upper: Upperinitedlower: ลดลง
คุณพบความแตกต่างในรหัสหรือไม่?
ใช่ฟิลด์ lowerString นี้ไม่ได้ตั้งค่าให้ว่างเปล่าอีกต่อไป ทำไมสิ่งนี้ทำให้แตกต่าง? อย่างไรก็ตามค่าเริ่มต้นของฟิลด์ประเภทอ้างอิง (เช่น String ที่นี่) ว่างเปล่า? แน่นอนว่ามันว่างเปล่า ปรากฎว่าในขณะที่การเปลี่ยนแปลงเล็กน้อยนี้เห็นได้ชัดว่าไม่เปลี่ยนพฤติกรรมของรหัสในทางใดทางหนึ่งมันทำให้ผลลัพธ์แตกต่างกัน
แล้วเกิดอะไรขึ้นกันแน่? ทุกอย่างชัดเจนเมื่อตรวจสอบลำดับการเริ่มต้น:
1. ฟังก์ชั่น main() เรียกตัวสร้าง Lower
2. อินสแตนซ์ของ Lower พร้อม หมายความว่าฟิลด์ทั้งหมดถูกสร้างและกรอกด้วยค่าเริ่มต้นตัวอย่างเช่นค่าเริ่มต้นของประเภทการอ้างอิงนั้นว่างเปล่าและค่าเริ่มต้นของประเภทบูลีนเป็น false ในเวลานี้ไม่มีการมอบหมายแบบอินไลน์ให้กับฟิลด์
3. ตัวสร้างคลาสแม่เรียกว่า สิ่งนี้ถูกบังคับใช้โดยลักษณะของภาษา ดังนั้นก่อนที่จะมีสิ่งอื่นเกิดขึ้นตัวสร้างของ Upper จะถูกเรียก
4.upper คอนสตรัคเตอร์นี้ทำงานและระบุการอ้างอิงไปยังอินสแตนซ์ที่สร้างขึ้นใหม่ของวิธี Initializer.initialize()
5. คลาส Initializer แนบสตริงใหม่กับสองฟิลด์ ( upperString และ upperstring และ lowerString ) การกำหนดค่าให้กับสองฟิลด์เหล่านั้นโดยใช้ instanceof ที่สกปรกเล็กน้อยของการตรวจสอบอินสแตนซ์ไม่ใช่รูปแบบการออกแบบที่ดีโดยเฉพาะ แต่ก็ใช้งานได้ไม่ต้องกังวลมากนัก เมื่อสิ่งนั้นเกิดขึ้นการอ้างอิงถึง upperString และ lowerString จะไม่ว่างเปล่าอีกต่อไป
6. การเรียกใช้ Initializer.initialize() เสร็จสมบูรณ์และตัวสร้าง Upper ก็เสร็จสมบูรณ์เช่นกัน
7. ตอนนี้มันเริ่มน่าสนใจ: การสร้างอินสแตนซ์ Lower ยังคงดำเนินต่อไป สมมติว่าการมอบหมาย =null ไม่ได้ระบุไว้อย่างชัดเจนในการประกาศฟิลด์ lowerString , ตัวสร้าง Lower ดำเนินการดำเนินการดำเนินการต่อและพิมพ์สองสตริงที่เชื่อมต่อกับฟิลด์
อย่างไรก็ตามหากมีการดำเนินการที่กำหนด NULL อย่างชัดเจนกระบวนการดำเนินการจะแตกต่างกันเล็กน้อย: เมื่อตัวสร้างคลาสแม่เสร็จสมบูรณ์การเริ่มต้นตัวแปรใด ๆ จะดำเนินการก่อนที่ส่วนที่เหลือของตัวสร้างจะทำงาน (ดูหัวข้อ 12.5 ของข้อกำหนดภาษา Java) ในกรณีนี้การอ้างอิงสตริงที่กำหนดให้กับ lowerString ก่อนหน้านี้จะไม่ได้รับมอบหมายอีกครั้ง จากนั้นดำเนินการต่อการสร้างฟังก์ชั่นที่เหลืออยู่และตอนนี้พิมพ์ค่าของ lowerString เป็น: NULL
นี่เป็นตัวอย่างที่ดีไม่เพียง แต่จะช่วยให้เราสนใจรายละเอียดบางอย่างเกี่ยวกับการสร้างวัตถุ (หรือเพื่อทราบว่าจะตรวจสอบข้อกำหนดการเข้ารหัส Java พิมพ์หรือออนไลน์ได้ที่ไหน) แต่ยังแสดงให้เห็นว่าทำไมการเขียนการเริ่มต้นเช่นนี้ไม่ดี เราไม่ควรสนใจเรื่องย่อยของ Upper เลย ในทางกลับกันหากด้วยเหตุผลบางอย่างการเริ่มต้นฟิลด์บางอย่างไม่สามารถทำได้ในคลาสย่อยของตัวเองมันจะต้องใช้ตัวแปรบางอย่างของคลาสผู้ช่วยเริ่มต้นของตัวเองเท่านั้น ในกรณีนี้หากคุณใช้ String lowString หรือ String lowerString = null ไม่มีความแตกต่างจริงๆมันควรจะเป็นอย่างไร
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะช่วยในการศึกษาหรือทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร