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
คลาส พวกเขาต้องการทำให้เป็นคลาสสากล เพื่อให้สามารถเก็บออบเจกต์ประเภทใดก็ได้ ดังนั้นพวกเขาจึงใช้อาร์เรย์ของObject
s เพื่อเก็บองค์ประกอบต่างๆ
จุดแข็งของวิธีนี้คือคุณสามารถเพิ่มวัตถุประเภทใดก็ได้ในคอลเลกชัน
แน่นอนว่ามีจุดอ่อนหลายประการ
ข้อเสีย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