1. การเริ่มต้นตัวแปร
ดังที่คุณทราบแล้ว คุณสามารถประกาศตัวแปรหลายตัวในคลาสของคุณ และไม่เพียงแต่ประกาศตัวแปรเท่านั้น แต่ยังกำหนดค่าเริ่มต้นให้กับตัวแปรเหล่านั้นได้ทันทีด้วย
และตัวแปรเดียวกันนี้สามารถเริ่มต้นในตัวสร้างได้เช่นกัน ซึ่งหมายความว่าตามทฤษฎีแล้ว ตัวแปรเหล่านี้สามารถกำหนดค่าได้สองครั้ง ตัวอย่าง
รหัส | บันทึก |
---|---|
|
ตัวแปร age ถูกกำหนดค่าเริ่มต้น ค่าเริ่มต้นถูกเขียนทับ ตัวแปรอายุเก็บค่าเริ่มต้น |
|
สิ่งนี้ได้รับอนุญาต: คอนสตรัคเตอร์แรกจะถูกเรียก |
|
สิ่งนี้ได้รับอนุญาต: ตัวสร้างที่สองจะถูกเรียก |
นี่คือสิ่งที่เกิดขึ้นเมื่อCat cat = new Cat("Whiskers", 2);
ดำเนินการ:
Cat
มีการสร้างวัตถุ- ตัวแปรอินสแตนซ์ทั้งหมดจะเริ่มต้นด้วยค่าเริ่มต้น
- คอนสตรัคเตอร์ถูกเรียกและรันโค้ด
กล่าวอีกนัยหนึ่ง ตัวแปรจะได้รับค่าเริ่มต้นก่อน จากนั้นรหัสของคอนสตรัคเตอร์จะถูกดำเนินการเท่านั้น
2. ลำดับการเริ่มต้นของตัวแปรในคลาส
ตัวแปรไม่ได้ถูกเริ่มต้นก่อนที่คอนสตรัคเตอร์จะทำงานเท่านั้น แต่จะถูกเตรียมใช้งานตามลำดับที่กำหนดไว้อย่างดี: ลำดับที่ตัวแปรถูกประกาศในคลาส
ลองดูโค้ดที่น่าสนใจ:
รหัส | บันทึก |
---|---|
|
รหัสนี้จะไม่คอมไพล์เนื่องจากในขณะที่a
สร้างตัวแปรยังไม่มีb
และc
ตัวแปร แต่คุณสามารถเขียนโค้ดได้ดังนี้ — โค้ดนี้จะคอมไพล์และทำงานได้ดี
รหัส | บันทึก |
---|---|
|
0 0+2 0+2+3 |
แต่โปรดจำไว้ว่ารหัสของคุณต้องโปร่งใสสำหรับนักพัฒนารายอื่น เป็นการดีกว่าที่จะไม่ใช้เทคนิคเช่นนี้ เนื่องจากจะทำให้โค้ดอ่านไม่ออก
ที่นี่เราต้องจำไว้ว่าก่อนที่จะกำหนดค่าตัวแปรจะมีค่าเริ่มต้น สำหรับint
ประเภทนี้ ค่านี้เป็นศูนย์
เมื่อ JVM เริ่มต้นa
ตัวแปร มันจะกำหนดค่าเริ่มต้นสำหรับประเภท int: 0
เมื่อถึงb
ตัวแปร a จะเป็นที่รู้จักและมีค่าอยู่แล้ว ดังนั้น JVM จะกำหนดค่าให้เป็น 2
และเมื่อถึงc
ตัวแปร ตัวแปรa
และb
จะถูกเตรียมใช้งาน ดังนั้น JVM จะคำนวณค่าเริ่มต้นสำหรับc
: 0+2+3 ได้ อย่างง่ายดาย
หากคุณสร้างตัวแปรภายในเมธอด คุณจะไม่สามารถใช้มันได้เว้นแต่คุณจะกำหนดค่าให้กับมันก่อนหน้านี้ แต่นี่ไม่เป็นความจริงสำหรับตัวแปรของคลาส! ถ้าไม่ได้กำหนดค่าเริ่มต้นให้กับตัวแปรของคลาส ก็จะมีการกำหนดค่าเริ่มต้น
3. ค่าคงที่
ในขณะที่เรากำลังวิเคราะห์วิธีการสร้างออบเจกต์ มันก็คุ้มค่าที่จะพิจารณาการกำหนดค่าเริ่มต้นของค่าคงที่ เช่น ตัวแปรที่มีตัวfinal
ปรับแต่ง
หากตัวแปรมีfinal
ตัวแก้ไข จะต้องกำหนดค่าเริ่มต้น คุณรู้เรื่องนี้แล้วและไม่มีอะไรน่าประหลาดใจเกี่ยวกับเรื่องนี้
แต่สิ่งที่คุณไม่รู้ก็คือ คุณไม่จำเป็นต้องกำหนดค่าเริ่มต้นทันที หากคุณกำหนดในคอนสตรัคเตอร์ สิ่งนี้จะใช้ได้ดีสำหรับตัวแปรสุดท้าย ข้อกำหนดเพียงอย่างเดียวคือถ้าคุณมีตัวสร้างหลายตัว ตัวแปรสุดท้ายจะต้องกำหนดค่าในตัวสร้างแต่ละตัว
ตัวอย่าง:
public class Cat
{
public final int maxAge = 25;
public final int maxWeight;
public Cat (int weight)
{
this.maxWeight = weight; // Assign an initial value to the constant
}
}
4. รหัสในตัวสร้าง
และหมายเหตุสำคัญอีกสองสามข้อเกี่ยวกับตัวสร้าง ต่อมา เมื่อคุณเรียนรู้ Java ต่อไป คุณจะพบกับสิ่งต่างๆ เช่น การสืบทอด การทำให้เป็นอันดับ ข้อยกเว้น ฯลฯ สิ่งเหล่านี้ล้วนมีอิทธิพลต่อการทำงานของคอนสตรัคเตอร์ในระดับที่แตกต่างกันไป มันไม่สมเหตุสมผลเลยที่จะลงลึกในหัวข้อเหล่านี้ แต่อย่างน้อยเราจำเป็นต้องสัมผัสกับสิ่งเหล่านี้
ตัวอย่างเช่น ต่อไปนี้เป็นข้อสังเกตที่สำคัญเกี่ยวกับคอนสตรัคเตอร์ ในทางทฤษฎี คุณสามารถเขียนโค้ดที่มีความซับซ้อนเท่าใดก็ได้ในตัวสร้าง แต่อย่าทำแบบนี้ ตัวอย่าง:
|
เปิดสตรีมอ่านไฟล์ อ่านไฟล์เป็นอาร์เรย์ไบต์ บันทึกอาร์เรย์ไบต์เป็นสตริง แสดงเนื้อหาของไฟล์บนหน้าจอ |
ในตัวสร้างคลาส FilePrinter เราเปิดสตรีมไบต์บนไฟล์ทันทีและอ่านเนื้อหา นี่เป็นลักษณะการทำงานที่ซับซ้อนและอาจส่งผลให้เกิดข้อผิดพลาด
จะทำอย่างไรหากไม่มีไฟล์ดังกล่าว จะเกิดอะไรขึ้นหากมีปัญหาในการอ่านไฟล์ ถ้ามันใหญ่เกินไปล่ะ?
ตรรกะที่ซับซ้อนแสดงถึงความเป็นไปได้สูงที่จะเกิดข้อผิดพลาด และนั่นหมายความว่าโค้ดต้องจัดการกับข้อยกเว้นอย่างถูกต้อง
ตัวอย่างที่ 1 — การทำให้เป็นอนุกรม
ในโปรแกรม Java มาตรฐาน มีหลายสถานการณ์ที่คุณไม่ได้เป็นคนสร้างอ็อบเจกต์ของคลาสของคุณ ตัวอย่างเช่น สมมติว่าคุณตัดสินใจส่งออบเจกต์ผ่านเครือข่าย ในกรณีนี้ เครื่อง Java จะแปลงออบเจ็กต์ของคุณเป็นชุดของไบต์ ส่ง และสร้างออบเจกต์ใหม่จากชุดของไบต์
แต่สมมติว่าไฟล์ของคุณไม่มีอยู่ในคอมพิวเตอร์เครื่องอื่น จะมีข้อผิดพลาดในตัวสร้างและไม่มีใครจัดการได้ และนั่นค่อนข้างสามารถทำให้โปรแกรมยุติได้
ตัวอย่างที่ 2 — การเริ่มต้นฟิลด์ของคลาส
หากตัวสร้างคลาสของคุณสามารถโยนข้อยกเว้นที่ตรวจสอบได้ เช่น ทำเครื่องหมายด้วยคีย์เวิร์ด Throws คุณต้องตรวจจับข้อยกเว้นที่ระบุในเมธอดที่สร้างวัตถุของคุณ
แต่ถ้าไม่มีวิธีการดังกล่าวล่ะ? ตัวอย่าง:
รหัส | บันทึก |
---|---|
|
รหัสนี้จะไม่รวบรวม |
ตัวFilePrinter
สร้างคลาสสามารถโยนข้อยกเว้นที่ตรวจสอบได้ซึ่งหมายความว่าคุณไม่สามารถสร้างFilePrinter
ออบเจกต์โดยไม่ล้อมมันไว้ในบล็อก try-catch และบล็อก try-catch สามารถเขียนได้ในเมธอดเท่านั้น
5. ตัวสร้างคลาสพื้นฐาน
ในบทที่แล้ว เราได้กล่าวถึงมรดกเล็กน้อย น่าเสียดายที่การสนทนาแบบเต็มของเราเกี่ยวกับการสืบทอดและ OOP ถูกสงวนไว้สำหรับระดับที่ทุ่มเทให้กับ OOP และการสืบทอดตัวสร้างนั้นเกี่ยวข้องกับเราอยู่แล้ว
ถ้าคลาสของคุณสืบทอดคลาสอื่น วัตถุของคลาสแม่จะถูกฝังอยู่ภายในวัตถุของคลาสของคุณ ยิ่งไปกว่านั้น คลาสพาเรนต์ยังมีตัวแปรและตัวสร้างของตัวเอง
ซึ่งหมายความว่าเป็นสิ่งสำคัญมากที่คุณจะต้องรู้และเข้าใจว่าตัวแปรถูกเตรียมใช้งานอย่างไรและตัวสร้างถูกเรียกเมื่อคลาสของคุณมีคลาสพาเรนต์และคุณสืบทอดตัวแปรและเมธอดของคลาสนั้น
ชั้นเรียน
เราจะทราบลำดับที่ตัวแปรเริ่มต้นและเรียกตัวสร้างได้อย่างไร เริ่มต้นด้วยการเขียนโค้ดสำหรับสองคลาส คนหนึ่งจะได้รับมรดกอีกคนหนึ่ง:
รหัส | บันทึก |
---|---|
|
คลาส ChildClass สืบทอดParentClass คลาส |
เราจำเป็นต้องกำหนดลำดับในการเริ่มต้นตัวแปรและเรียกคอนสตรัคเตอร์ การบันทึกจะช่วยให้เราทำสิ่งนี้ได้
การบันทึก
การบันทึกเป็นกระบวนการของการบันทึกการกระทำที่ดำเนินการโดยโปรแกรมขณะที่มันทำงาน โดยเขียนลงในคอนโซลหรือไฟล์
มันค่อนข้างง่ายที่จะระบุว่าคอนสตรัคเตอร์ถูกเรียก: ในเนื้อหาของคอนสตรัคเตอร์ ให้เขียนข้อความไปยังคอนโซล แต่คุณจะทราบได้อย่างไรว่าตัวแปรได้รับการเริ่มต้นแล้ว?
จริงๆ แล้ว มันก็ไม่ใช่เรื่องยากเช่นกัน: เขียนเมธอดพิเศษที่จะคืนค่าที่ใช้ในการเริ่มต้นตัวแปร และบันทึกการเริ่มต้น นี่คือลักษณะของรหัส:
รหัสสุดท้าย
|
สร้าง ChildClass วัตถุ วิธีนี้เขียนข้อความที่ส่งผ่านไปยังคอนโซลและส่งกลับ ประกาศ ParentClass คลาสแสดงข้อความ และเริ่มต้นตัวแปรด้วย เขียนข้อความว่าตัวสร้างถูกเรียก ละเว้นค่าส่งคืน ประกาศ ChildClass คลาสแสดงข้อความ และเริ่มต้นตัวแปรด้วย เขียนข้อความว่าตัวสร้างถูกเรียก ละเว้นค่าส่งคืน |
หากคุณรันโค้ดนี้ ข้อความจะแสดงบนหน้าจอดังนี้:
เอาต์พุตคอนโซลของเมธอดMain.print() |
---|
|
คุณจึงมั่นใจได้เสมอว่าตัวแปรของคลาสได้รับการเริ่มต้นก่อนที่จะเรียกคอนสตรัคเตอร์ คลาสพื้นฐานได้รับการเริ่มต้นอย่างสมบูรณ์ก่อนที่จะเริ่มต้นคลาสที่สืบทอดมา
GO TO FULL VERSION