เครื่องหมายคำถามในพารามิเตอร์ประเภท Java generics หมายถึงอะไร


216

นี่เป็นข้อมูลโค้ดขนาดเล็กที่นำมาจากตัวอย่างบางส่วนที่มาพร้อมกับ Stanford Parser ฉันได้รับการพัฒนาใน Java ประมาณ 4 ปี แต่ไม่เคยมีความเข้าใจที่ดีมากในสิ่งที่รูปแบบของรหัสนี้ควรจะระบุ

List<? extends HasWord> wordList = toke.tokenize();

ฉันไม่กังวลเกี่ยวกับรายละเอียดของรหัส สิ่งที่ฉันสับสนเกี่ยวกับสิ่งที่แสดงออกทั่วไปควรจะถ่ายทอดในภาษาอังกฤษ

บางคนสามารถอธิบายเรื่องนี้กับฉันได้ไหม


คำตอบ:


226
? extends HasWord

หมายถึง "คลาส / อินเทอร์เฟซที่ขยายHasWord" ในคำอื่น ๆHasWordของตัวเองหรือของเด็ก ... อะไรโดยทั่วไปที่จะทำงานร่วมกับบวกinstanceof HasWordnull

ในคำศัพท์ทางเทคนิคเพิ่มเติม? extends HasWordสัญลักษณ์ตัวแทนมีขอบเขตซึ่งครอบคลุมในรายการ 31 ของEffective Java 3rd Editionเริ่มต้นที่หน้า 139 บทที่เดียวกันจากรุ่นที่ 2 มีให้บริการออนไลน์ในรูปแบบ PDF ; ส่วนของ wildcard ที่ถูกล้อมคือรายการที่ 28 เริ่มต้นที่หน้า 134

อัปเดต: ลิงค์ PDF ได้รับการอัปเดตตั้งแต่ Oracle ลบทิ้งไปครู่หนึ่ง ตอนนี้ชี้ไปที่สำเนาที่โฮสต์โดยคณะวิชาวิศวกรรมอิเล็กทรอนิกส์และวิทยาศาสตร์คอมพิวเตอร์ของมหาวิทยาลัย Queen Mary

อัปเดต 2: ให้รายละเอียดมากขึ้นว่าทำไมคุณต้องการใช้ไวด์การ์ด

ถ้าคุณประกาศวิธีการที่มีลายเซ็นคาดหวังให้คุณผ่านแล้วสิ่งเดียวที่คุณสามารถส่งผ่านเป็นList<HasWord>List<HasWord>

อย่างไรก็ตามหากลายเซ็นดังกล่าวList<? extends HasWord>นั้นคุณสามารถส่งList<ChildOfHasWord>แทน

ทราบว่ามีความแตกต่างที่ลึกซึ้งระหว่างและList<? extends HasWord> List<? super HasWord>ดังที่ Joshua Bloch กล่าวไว้: PECS = โปรดิวเซอร์ - ขยาย - บริโภค - ยอดเยี่ยม

สิ่งที่หมายถึงนี้ก็คือว่าถ้าคุณจะผ่านในคอลเลกชันที่วิธีการของคุณดึงข้อมูลออกจาก (เช่นคอลเลกชันคือการผลิตองค์ประกอบสำหรับวิธีการของคุณเพื่อใช้งาน) extendsคุณควรใช้ หากคุณกำลังผ่านในคอลเลกชันที่วิธีการของคุณเพิ่มข้อมูลไป (เช่นคอลเลกชันที่มีการบริโภคองค์ประกอบวิธีการของคุณสร้าง) superก็ควรใช้

นี่อาจฟังดูสับสน อย่างไรก็ตามคุณสามารถเห็นมันในList's sortคำสั่ง (ซึ่งเป็นเพียงทางลัดไปยังรุ่นสองหาเรื่องของ Collections.sort ก) แทนการก็จริงยิงComparator<T> Comparator<? super T>ในกรณีนี้เครื่องมือเปรียบเทียบใช้องค์ประกอบของรายการListเพื่อเรียงลำดับรายการใหม่


17
"ทุกอย่างที่จะทำงานกับ instanceof" - บวกค่า Null โปรดจำไว้ว่าค่า Null ส่งคืนเท็จสำหรับการตรวจสอบอินสแตนซ์ใด ๆ
Eyal Schneider

12
อย่าลืมอินเตอร์เฟส การ ไม่ต้องเป็นตัวแทนของคลาส!
Mark Peters

9
List<HasWord>เป็นสิ่งที่คุณอธิบาย: รายการที่มีวัตถุใด ๆxที่ผลตอบแทนจริงและx instanceof HasWord nullคุณไม่ต้องการสัญลักษณ์แทนสำหรับสิ่งนี้ HasWordหมายถึงสัญลักษณ์แทนว่ามันสามารถจริงจะรายการอีกประเภทหนึ่งเช่นกันตราบใดชนิดนี้เป็นชนิดย่อยของ (ขออภัยสำหรับความคิดเห็นที่ล่าช้า)
Paŭlo Ebermann

1
ลิงค์ PDF ดูเหมือนจะไม่ทำงาน แต่สิ่งนี้มีประโยชน์สำหรับฉัน: docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
user1338062

แปลกมากฉันไม่เคยได้รับข้อความเมื่อปีที่แล้วเมื่อ @ user1338062 โพสต์และไม่รู้ว่าลิงค์ PDF ใช้งานไม่ได้ แก้ไขแล้ว ฉันยังเพิ่มลิงก์ไปยังหนังสือด้วย
Powerlord

65

เครื่องหมายคำถามเป็นตัวบ่งชี้สำหรับ 'ประเภทใด ๆ ' ?คนเดียวหมายถึง

การขยายประเภทใด ๆObject(รวมถึงObject)

ในขณะที่ตัวอย่างของคุณหมายถึง

ชนิดใดก็ได้ที่ขยายหรือนำไปใช้ HasWord(รวมถึงHasWordถ้า HasWordเป็นคลาสที่ไม่เป็นนามธรรม)


2
ดังนั้นpublic Set<Class<?>> getClasses()หมายความว่าอย่างไร ความแตกต่างSet<Class>คืออะไร? javax.ws.rs.core.Applicationฉันกำลังมองหาที่
ห้องนิรภัย

14

List<? extends HasWord>ยอมรับคลาสที่เป็นรูปธรรมใด ๆ ที่ขยาย HasWord หากคุณมีคลาสต่อไปนี้ ...

public class A extends HasWord { .. }
public class B extends HasWord { .. }
public class C { .. }
public class D extends SomeOtherWord { .. }

... wordListสามารถมีได้เฉพาะรายการของ As หรือ B หรือทั้งสองอย่างเนื่องจากทั้งสองคลาสจะขยายพาเรนต์เดียวกันหรือnull (ซึ่งไม่สามารถตรวจสอบอินสแตนซ์ของHasWorld)


8
ไม่เพียง แต่เป็นรูปธรรมเท่านั้น
bloparod

2
ไม่เพียง แต่ที่เป็นรูปธรรมและนามธรรม subclasses List<? extends Collection<String>> list = new ArrayList<List<String>>();แต่ยังย่อยอินเตอร์เฟซ:
Mark Peters

2
คุณไม่จำเป็นต้องใช้สัญลักษณ์แทนสำหรับสิ่งนี้จริง ๆ แล้ว: List<HasWord>ทำได้ดีสำหรับสิ่งนี้ จุดนี่คือว่าตัวแปรนี้สามารถมีList<A>หรือเช่นเดียวกับList<B> List<HasWord>
Paŭlo Ebermann

12

บางทีตัวอย่าง "โลกแห่งความจริง" ที่วางแผนไว้อาจช่วยได้

ที่ทำงานของฉันเรามีถังขยะที่มีรสชาติแตกต่างกัน ถังขยะทั้งหมดมีขยะ แต่ถังขยะบางถังเป็นผู้เชี่ยวชาญและไม่เก็บขยะทุกประเภท ดังนั้นเราจึงมีBin<CupRubbish>และBin<RecylcableRubbish>และระบบประเภทต้องการให้แน่ใจว่าฉันไม่สามารถใส่HalfEatenSandwichRubbishประเภทใดประเภทหนึ่งได้ แต่สามารถเข้าไปในถังขยะทั่วไปBin<Rubbish>ได้ ถ้าผมต้องการที่จะพูดคุยเกี่ยวกับBinการซึ่งอาจจะเป็นความเชี่ยวชาญดังนั้นฉันไม่สามารถใส่ในขยะเข้ากันไม่ได้แล้วที่จะเป็นRubbishBin<? extends Rubbish>

(หมายเหตุ: ? extendsไม่ได้หมายถึงอ่านอย่างเดียวตัวอย่างเช่นฉันสามารถใช้ความระมัดระวังอย่างเหมาะสมนำขยะออกจากถังขยะที่ไม่ทราบชนิดและต่อมานำกลับมาไว้ในที่อื่น)

ไม่แน่ใจว่าจะช่วยได้มากแค่ไหน ตัวชี้ไปยังตัวชี้ต่อหน้า polymorphism ไม่ชัดเจนทั้งหมด


5

เป็นภาษาอังกฤษ:

มันเป็นListประเภทที่ขยายคลาสHasWordรวมถึงHasWord

โดยทั่วไปข้อมูล?ทั่วไปหมายถึงคลาสใด ๆ และextends SomeClassระบุว่าวัตถุนั้นจะต้องขยายSomeClass(หรือเป็นคลาสนั้น)


1
ที่จริงพิมพ์แทนระดับ มันใช้งานได้ดีสำหรับอินเตอร์เฟส
Paŭlo Ebermann

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.