1. สืบทอดทุกคลาสObject
คลาสทั้งหมดใน Java สืบทอดObjectคลาส โดยปริยาย
เราจะวิเคราะห์ว่ามรดกคืออะไรและทำงานอย่างไรใน Java ในภารกิจ Java Core สำหรับตอนนี้ เราจะพิจารณาข้อเท็จจริงง่ายๆ ประการหนึ่งต่อไปนี้:
สามารถกำหนดวัตถุของคลาสใดก็ได้ให้กับObjectตัวแปร ตัวอย่าง:
| รหัส | บันทึก |
|---|---|
|
ตัวแปรoเก็บการอ้างอิงถึงScannerวัตถุ |
|
ตัวแปรoเก็บการอ้างอิงถึงStringวัตถุ |
|
ตัวแปรoเก็บการอ้างอิงถึงIntegerวัตถุ |
|
ตัวแปรoเก็บการอ้างอิงถึงStringวัตถุ |
นี่คือจุดสิ้นสุดของข่าวดี คอมไพลเลอร์ไม่ติดตามประเภทดั้งเดิมของวัตถุที่บันทึกไว้ในObjectตัวแปร ดังนั้นคุณจึงไม่สามารถ เรียกใช้เมธอดบนวัตถุที่บันทึกไว้นอกเหนือจากเมธอดของObjectคลาส
หากคุณต้องการเรียกใช้เมธอดที่เกี่ยวข้องกับประเภทดั้งเดิมของออบเจ็กต์ คุณต้องบันทึกการอ้างอิงถึงเมธอดในตัวแปรประเภทที่ถูกต้องก่อน จากนั้นจึงเรียกใช้เมธอดในตัวแปรนั้น:
| รหัส | บันทึก |
|---|---|
|
โปรแกรมจะไม่คอมไพล์ ชั้นObjectเรียนไม่มีnextInt()วิธีการ |
|
สิ่งนี้จะทำงาน ที่นี่เราบันทึกการอ้างอิงถึงวัตถุ ScannerในScannerตัวแปรโดยใช้ตัวดำเนินการ typecast |
คุณไม่สามารถไปกำหนดObjectตัวแปรให้กับตัวแปร Scanner ได้ แม้ว่าObjectตัวแปรจะเก็บการอ้างอิงScannerวัตถุ ก็ตาม แต่คุณสามารถทำได้หากคุณใช้ตัวดำเนินการ typecastซึ่งคุณรู้อยู่แล้ว นี่คือลักษณะทั่วไป:
Type name1 = (Type) name2;
name1ชื่อของตัวแปรอยู่ที่ไหนTypeและname2เป็นชื่อของObjectตัวแปรที่เก็บการอ้างอิงถึงTypeวัตถุ
การพิมพ์
หากประเภทของตัวแปรและประเภทของวัตถุไม่ตรงกัน จากนั้น a ClassCastExceptionจะถูกโยนทิ้ง ตัวอย่าง:
| รหัส | บันทึก |
|---|---|
|
ข้อผิดพลาดจะเกิดขึ้นที่รันไทม์: a ClassCastExceptionจะถูกส่งมาที่นี่ |
มีวิธีหลีกเลี่ยงข้อผิดพลาดนี้ใน Java: เราทำได้โดยตรวจสอบประเภทของวัตถุที่จัดเก็บไว้ในตัวแปร :
name instanceof Type
ตัวinstanceofดำเนินการตรวจสอบว่าnameตัวแปรเป็นTypeวัตถุหรือไม่
ตัวอย่างเช่น ลองค้นหาสตริงในอาร์เรย์ของออบเจกต์ที่หลากหลาย:
| รหัส | บันทึก |
|---|---|
|
การทำกล่องอัตโนมัติจะแปลงค่าเหล่านี้เป็นInteger, String, และDoubleตามลำดับ วนซ้ำอาร์เรย์ของอ็อบเจกต์ ถ้าอ Stringอบเจกต์นั้นเป็นแบบบันทึกไปยัง Stringตัวแปรแสดงตัวแปรบนหน้าจอ |
2. เหตุใดยาชื่อสามัญจึงปรากฏขึ้น - คอลเลกชัน
กลับไปที่คอลเลกชันกันเถอะ
ทันทีที่ผู้พัฒนา Java สร้างArrayListคลาส พวกเขาต้องการทำให้เป็นคลาสสากล เพื่อให้สามารถเก็บออบเจกต์ประเภทใดก็ได้ ดังนั้นพวกเขาจึงใช้อาร์เรย์ของObjects เพื่อเก็บองค์ประกอบต่างๆ
จุดแข็งของวิธีนี้คือคุณสามารถเพิ่มวัตถุประเภทใดก็ได้ในคอลเลกชัน
แน่นอนว่ามีจุดอ่อนหลายประการ
ข้อเสีย1.
จำเป็นต้องเขียนตัวดำเนินการแปลงประเภทเสมอเมื่อดึงองค์ประกอบจากคอลเล็กชัน:
| รหัส | บันทึก |
|---|---|
|
สร้างคอลเลกชันเพื่อจัดเก็บการอ้างอิงถึงObjectวัตถุเติมคอลเลกชันด้วยตัวเลข 10, 20, ... 100; รวมองค์ประกอบของคอลเลก ชัน Typecasting เป็นสิ่งจำเป็น |
ข้อเสีย 2.
ไม่มีการรับประกันว่าคอลเลกชันมีองค์ประกอบเฉพาะประเภท
| รหัส | บันทึก |
|---|---|
|
สร้างคอลเลกชันเพื่อจัดเก็บการอ้างอิงถึงObjectวัตถุเราเติมคอลเลกชันด้วยตัวเลขที่แสดงเป็น Doubleวัตถุ: 0.0, 2.5, 5.0, ... รวมองค์ประกอบของคอล เลก ชัน จะมีข้อผิดพลาด: a Doubleไม่สามารถส่งไปยังInteger |
สามารถใส่ข้อมูลลงในคอลเลกชันได้ทุกที่:
- ด้วยวิธีอื่น
- ในโปรแกรมอื่น
- จากไฟล์
- ผ่านเครือข่าย
ข้อเสีย3.
ข้อมูลในคอลเลกชันสามารถเปลี่ยนแปลงได้โดยไม่ตั้งใจ
คุณสามารถส่งคอลเลกชันที่เต็มไปด้วยข้อมูลของคุณไปยังวิธีการบางอย่าง วิธีการนั้นเขียนโดยโปรแกรมเมอร์อื่น เพิ่มข้อมูลลงในคอลเลกชันของคุณ
ชื่อของคอลเล็กชันไม่ได้ระบุอย่างชัดเจนว่าสามารถเก็บข้อมูลประเภทใดได้บ้าง และแม้ว่าคุณจะตั้งชื่อตัวแปรของคุณอย่างชัดเจน แต่การอ้างอิงถึงตัวแปรนั้นสามารถส่งต่อไปยังเมธอดต่างๆ ได้นับสิบเมธอด และเมธอดเหล่านั้นจะไม่รู้อะไรเลยเกี่ยวกับชื่อดั้งเดิมของตัวแปร
3. ยาสามัญ

ใน Java ปัญหาเหล่านี้จะหมดไปโดยสิ่งเจ๋งๆ ที่เรียกว่า generics
ใน Java ข้อมูลทั่วไปหมายถึงความสามารถในการเพิ่มพารามิเตอร์ประเภทให้กับประเภท ผลลัพธ์คือประเภทคอมโพสิตที่ซับซ้อน มุมมองทั่วไปของประเภทคอมโพสิตคือ:
ClassName<TypeParameter>
นี่คือคลาสทั่วไป และสามารถใช้ได้ทุกที่ที่คุณใช้ชั้นเรียนตามปกติ
| รหัส | คำอธิบาย |
|---|---|
|
การสร้างตัวแปร |
|
การสร้างวัตถุ |
|
การสร้างอาร์เรย์ |
เฉพาะIntegerตัวแปรเท่านั้นที่สามารถจัดเก็บในคอลเลกชันดังกล่าวได้:
| รหัส | คำอธิบาย |
|---|---|
|
ArrayListคอลเลกชันที่มีIntegerองค์ประกอบได้รับอนุญาต และจะใช้งานได้เช่นกัน
กล่องอัตโนมัติ
แต่สิ่งนี้ไม่ได้รับอนุญาต: ข้อผิดพลาดในการรวบรวม |
คุณจะได้เรียนรู้วิธีสร้างคลาสของคุณเองด้วยพารามิเตอร์ประเภทในภารกิจ Java Collections สำหรับตอนนี้ เราจะดูวิธีการใช้งานและวิธีการทำงาน
4. ยาชื่อสามัญทำงานอย่างไร
ที่จริงแล้วยาชื่อสามัญนั้นมีความดั้งเดิมอย่างมาก
คอมไพเลอร์แทนที่ประเภททั่วไปด้วยประเภทสามัญ แต่เมื่อเมธอดของประเภททั่วไปถูกใช้ คอมไพเลอร์จะเพิ่มตัวดำเนินการ typecast เพื่อส่งพารามิเตอร์ไปยังพารามิเตอร์ประเภท:
| รหัส | สิ่งที่คอมไพเลอร์ทำ |
|---|---|
|
|
|
|
|
|
|
|
สมมติว่าเรามีวิธีที่รวมตัวเลขในชุดจำนวนเต็ม:
| รหัส | สิ่งที่คอมไพเลอร์ทำ |
|---|---|
|
|
กล่าวอีกนัยหนึ่ง ยาชื่อสามัญเป็นน้ำตาลวากยสัมพันธ์ชนิดหนึ่ง เหมือนกับการบอกอัตโนมัติ แต่เพิ่มเติมอีกเล็กน้อย ด้วย autoboxing คอมไพเลอร์จะเพิ่มเมธอดสำหรับการแปลง an intเป็น an Integerและในทางกลับกัน และสำหรับข้อมูลทั่วไปจะเพิ่มตัวดำเนินการ typecast
หลังจากที่คอมไพเลอร์คอมไพล์คลาสทั่วไปของคุณด้วยพารามิเตอร์ประเภทแล้ว คลาสเหล่านั้นจะถูกแปลงเป็นคลาสธรรมดาและตัวดำเนินการ typecast ข้อมูลเกี่ยวกับอาร์กิวเมนต์ประเภทที่ส่งผ่านไปยังตัวแปรประเภททั่วไปจะหายไป เอฟเฟกต์นี้เรียกอีกอย่างว่าการลบแบบ
บางครั้งโปรแกรมเมอร์ที่เขียนคลาสทั่วไป (คลาสที่มีพารามิเตอร์ประเภท) ต้องการข้อมูลเกี่ยวกับประเภทที่ส่งผ่านเป็นอาร์กิวเมนต์จริงๆ ในภารกิจ Java Collections คุณจะได้เรียนรู้วิธีจัดการกับสิ่งนี้และสิ่งที่เกี่ยวข้อง
5. ข้อเท็จจริงบางประการเกี่ยวกับยาชื่อสามัญ
ต่อไปนี้เป็นข้อเท็จจริงที่น่าสนใจเกี่ยวกับยาชื่อสามัญ
คลาสสามารถมีพารามิเตอร์หลายประเภท ดูเหมือนว่า:
ClassName<TypeParameter1, TypeParameter2, TypeParameter3>
จริงๆ แล้วนี่ไม่น่าแปลกใจเลย ในทุกที่ที่คอมไพเลอร์สามารถเพิ่มตัวดำเนินการเพื่อแคสต์เป็นประเภทเดียว ก็จะสามารถเพิ่มตัวดำเนินการประเภทแคสต์ได้หลายตัว
ตัวอย่าง:
| รหัส | บันทึก |
|---|---|
|
putพารามิเตอร์ตัวแรกของเมธอดคือ an และIntegerตัวที่สองคือ aString |
นอกจากนี้ยังสามารถใช้ประเภททั่วไปเป็นพารามิเตอร์ได้ อีกด้วย ดูเหมือนว่า:
ClassName<TypeParameter<TypeParameterParameter>>
สมมติว่าเราต้องการสร้างรายการที่จะจัดเก็บรายการสตริง ในกรณีนี้เราจะได้สิ่งนี้:
// List of greetings
ArrayList<String> listHello = new ArrayList<String>();
listHello.add ("Hello");
listHello.add ("Hi");
// List of goodbyes
ArrayList<String> listBye = new ArrayList<String>();
listBye.add("Bye");
listBye.add ("Goodbye");
// List of lists
ArrayList<ArrayList<String>> lists = new ArrayList<ArrayList<String>>();
lists.add(listHello);
lists.add(listBye);
ประเภททั่วไป (ประเภทที่มีพารามิเตอร์ประเภท) สามารถใช้เป็นประเภทอาร์เรย์ได้ ดูเหมือนว่า:
ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];
ไม่มีอะไรมหัศจรรย์เกิดขึ้นที่นี่: วงเล็บมุมระบุชื่อประเภท:
| รหัส | คู่ที่ไม่ใช่ทั่วไป |
|---|---|
|
|
|
|
|
|
GO TO FULL VERSION