UnsupportedOperationException ในอินเตอร์เฟสเฟรมเวิร์กของ Java คอลเล็กชัน


12

มองผ่าน Java (optional operation)คอลเลกชันกรอบฉันพบค่อนข้างน้อยของอินเตอร์เฟซที่มีการแสดงความคิดเห็น วิธีการเหล่านี้อนุญาตให้นำคลาสไปใช้ผ่านUnsupportedOperationExceptionหากพวกเขาไม่ต้องการใช้วิธีนั้น

ตัวอย่างนี้เป็นวิธีการในaddAllSet Interface

ตอนนี้ตามที่ระบุไว้ในชุดคำถามนี้อินเทอร์เฟซเป็นสัญญาที่กำหนดสำหรับสิ่งที่ผู้ใช้สามารถคาดหวังได้

อินเทอร์เฟซมีความสำคัญเนื่องจากแยกสิ่งที่คลาสทำจากวิธีการใช้งาน สัญญาที่กำหนดสิ่งที่ลูกค้าสามารถคาดหวังปล่อยให้นักพัฒนาสามารถนำไปใช้ได้ทุกวิธีที่พวกเขาเลือกตราบใดที่พวกเขารักษาสัญญา

และ

อินเทอร์เฟซคือคำอธิบายของการกระทำที่วัตถุสามารถทำได้ ... ตัวอย่างเช่นเมื่อคุณพลิกสวิตช์ไฟแสงจะสว่างขึ้นคุณไม่สนใจว่ามันจะทำอย่างไร ในการเขียนโปรแกรมเชิงวัตถุอินเทอร์เฟซคือคำอธิบายของฟังก์ชันทั้งหมดที่วัตถุต้องมีเพื่อให้เป็น "X"

และ

ฉันคิดว่าวิธีการทำงานบนอินเตอร์เฟสนั้นดีกว่าอย่างมาก จากนั้นคุณสามารถเยาะเย้ยการพึ่งพาของคุณได้อย่างดีและทุกอย่างก็น้อยกว่ากันอย่างแน่นหนา

จุดประสงค์ของอินเทอร์เฟซคืออะไร

อินเตอร์เฟสคืออะไร

อินเตอร์เฟส + ส่วนขยาย (มิกซ์อิน) เทียบกับคลาสพื้นฐาน

ระบุว่าวัตถุประสงค์ของอินเทอร์เฟซคือการกำหนดสัญญาและทำให้การพึ่งพาของคุณควบคู่กันอย่างอิสระไม่ได้มีวิธีการบางอย่างที่จะUnsupportedOperationExceptionทำลายวัตถุประสงค์ มันหมายความว่าฉันไม่สามารถผ่านSetและใช้งานaddAllได้อีกต่อไป แต่ฉันต้องรู้ว่าSetฉันใช้งานอะไรบ้างฉันจึงสามารถรู้ได้ว่าฉันสามารถใช้addAllหรือไม่ นั่นดูเหมือนจะไร้ค่าสำหรับฉัน

แล้วประเด็นUnsupportedOperationExceptionคืออะไร มันเป็นเพียงการสร้างรหัสดั้งเดิมและพวกเขาจำเป็นต้องทำความสะอาดอินเตอร์เฟสของพวกเขา? หรือว่ามันมีจุดประสงค์ที่ละเอียดอ่อนกว่าที่ฉันหลงหายไป?


ผมไม่ทราบว่า JRE คุณกำลังใช้ แต่รุ่น Oracle 8 ของฉันไม่ได้กำหนดในaddAll HashSetมันคล้อยตามการดำเนินการเริ่มต้นในAbstractCollectionซึ่งแน่นอนที่สุดไม่ได้UnsupportedOperationExceptionโยน

@Snowman คุณพูดถูก ฉันพลาดเอกสาร ฉันจะแก้ไขคำถามของฉัน
MirroredFate

1
ฉันต้องการเริ่มต้น Eclipse และดูซอร์สโค้ดกระดอนรอบการอ้างอิงรหัสและคำจำกัดความเพื่อให้แน่ใจว่าฉันถูกต้อง ตราบใดที่ JRE เชื่อมโยงกับsrc.zipมันก็ใช้งานได้ดี ช่วยให้ทราบได้อย่างชัดเจนว่าโค้ดที่ JRE กำลังทำงานอยู่บางครั้งและไม่เลื่อนไปที่ JavaDoc ซึ่งอาจเป็น verbose เล็กน้อย

คำตอบ:


12

ดูอินเตอร์เฟสต่อไปนี้:

อินเทอร์เฟซเหล่านี้ทั้งหมดประกาศวิธีการกลายพันธุ์เป็นทางเลือก นี่คือการบันทึกความจริงโดยนัยว่าคลาสCollectionsสามารถส่งกลับการนำไปใช้งานของอินเทอร์เฟซเหล่านั้นที่ไม่เปลี่ยนรูปนั่นคือการดำเนินการกลายพันธุ์ทางเลือกเหล่านั้นรับประกันว่าจะล้มเหลว อย่างไรก็ตามตามสัญญาใน JavaDoc การนำไปใช้งานทั้งหมดของอินเตอร์เฟสเหล่านั้นต้องอนุญาตการดำเนินการอ่าน ซึ่งรวมถึงการใช้งาน "ปกติ" เช่นHashSetและเช่นเดียวกับการเปลี่ยนรูปในห่อLinkedListCollections

ตรงกันข้ามกับอินเตอร์เฟสคิว:

อินเทอร์เฟซเหล่านี้ไม่ได้ระบุการดำเนินการทางเลือกใด ๆ : คิวตามคำนิยามออกแบบมาเพื่อนำเสนอและองค์ประกอบแบบสำรวจความคิดเห็นในลักษณะ FIFO คิวที่ไม่เปลี่ยนรูปนั้นเกี่ยวกับประโยชน์ของรถยนต์ที่ไม่มีล้อ


แนวคิดหนึ่งที่เกิดขึ้นซ้ำ ๆ กันคือการมีลำดับชั้นการสืบทอดที่มีทั้งวัตถุที่ไม่แน่นอนและไม่เปลี่ยนรูป อย่างไรก็ตามสิ่งเหล่านี้มีข้อบกพร่อง ความสลับซับซ้อนทำให้น้ำขุ่นโดยไม่ต้องแก้ปัญหาจริงๆ

  • สมมุติฐานSetอาจมีการดำเนินการอ่านและ subinterface MutableSetอาจมีการดำเนินการเขียน Liskovบอกเราว่าMutableSetสามารถส่งผ่านไปยังสิ่งที่ต้องการSetได้ ในตอนแรกฟังดูโอเค แต่พิจารณาวิธีการที่คาดว่าชุดข้อมูลอ้างอิงจะไม่ได้รับการแก้ไขในขณะที่อ่าน: เป็นไปได้ที่สองเธรดจะใช้ชุดเดียวกันและละเมิดค่าคงที่ของชุดที่ไม่เปลี่ยนแปลง นี่อาจทำให้เกิดปัญหาเช่นถ้าวิธีอ่านองค์ประกอบจากชุดสองครั้งและมันมีครั้งแรก แต่ไม่ใช่ครั้งที่สอง

  • Setไม่สามารถมีการใช้งานโดยตรงแทนที่จะมีMutableSetและImmutableSetเป็น subinterfaces ซึ่งจะใช้สำหรับการใช้งานคลาส สิ่งนี้มีปัญหาเหมือนข้างบน: ในบางช่วงของลำดับชั้นอินเทอร์เฟซมีค่าคงที่ที่ขัดแย้งกัน หนึ่งพูดว่า "ชุดนี้จะต้องไม่แน่นอน" และอีกคนหนึ่งพูดว่า "ชุดนี้ไม่สามารถเปลี่ยนแปลงได้"

  • อาจมีสองลำดับชั้นแยกกันโดยสิ้นเชิงสำหรับโครงสร้างข้อมูลที่ไม่แน่นอนและไม่เปลี่ยนรูป นี้จะเพิ่มตันของความซับซ้อนเป็นพิเศษสำหรับสิ่งที่สิ้นสุดขึ้นเป็นกำไรน้อยมาก สิ่งนี้ยังมีจุดอ่อนเฉพาะของวิธีการที่ไม่สนใจเกี่ยวกับความไม่แน่นอน (เช่นฉันต้องการย้ำรายการ) ตอนนี้ต้องรองรับสองอินเตอร์เฟสแยกกัน เนื่องจาก Java ถูกพิมพ์แบบสแตติกหมายถึงวิธีการพิเศษเพื่อจัดการลำดับชั้นของทั้งสองอินเตอร์เฟส

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


การอ่านที่เกี่ยวข้อง: เหตุใด Java 8 จึงไม่รวมคอลเล็กชันที่ไม่เปลี่ยนรูปแบบ


1
แต่ถ้าวิธีการเป็นตัวเลือกพวกเขาจะมีสถานที่ในอินเตอร์เฟซ? ไม่ควรมีอินเทอร์เฟซแยกต่างหากที่มีวิธีการเลือกใช้MutableCollectionใช่ไหม
MirroredFate

ไม่ไม่มีวิธีที่จะมีวัตถุที่เปลี่ยนแปลงไม่ได้และไม่เปลี่ยนรูปได้ในลำดับชั้นเดียวกันด้วยวิธีที่มีความหมายใด ๆ มีคำถามเมื่อเร็ว ๆ นี้ที่มีแผนผังที่ดีแสดงความซับซ้อนและคำอธิบายว่าทำไมมันถึงเป็นความคิดที่ไม่ดี แต่มันถูกลบไป บางทีคนอื่นรู้คำถามที่จะช่วยอธิบายเรื่องนี้ฉันไม่พบอะไรเลย แต่ฉันจะอัปเดตคำตอบเพื่ออธิบายเล็กน้อย

นั่นเป็นคำพูดทั่วไปเกี่ยวกับคิวที่ไม่เปลี่ยนรูปแบบ ผมใช้อย่างใดอย่างหนึ่งเพียงไม่กี่วันที่ผ่านมาในการแก้ปัญหานี้
Karl Bielefeldt

@Snowman แต่ดูเหมือนว่าจะทำให้วัตถุที่เปลี่ยนแปลงไม่ได้และไม่เปลี่ยนรูปนั้นเป็นสิ่งที่ตรงกันข้ามกัน ฉันคิดว่าวัตถุที่ไม่เปลี่ยนรูปนั้นเป็นเพียงวัตถุที่ขาดความสามารถในการกลายพันธุ์ จริงๆแล้วมันเป็นวิธีที่ซับซ้อนและยุ่งเหยิงมากขึ้นเพราะคุณต้องหาว่าอะไรคือการปรับใช้ที่ไม่แน่นอนและอะไรที่ไม่ได้เกิดขึ้น สำหรับฉันแล้วความแตกต่างเพียงอย่างเดียวระหว่างการใส่เมธอดทั้งหมดในอินเทอร์เฟซเดียวเมื่อเทียบกับการแยกวิธีที่ไม่แน่นอนเป็นหนึ่งในความชัดเจน
MirroredFate

@MirroredFate อ่านการแก้ไขล่าสุดของฉัน

2

มันเป็นพื้น YAGNI คอลเลกชันคอนกรีตทั้งหมดในไลบรารีมาตรฐานสามารถเปลี่ยนแปลงได้นำไปใช้หรือสืบทอดการดำเนินการทางเลือก พวกเขาไม่สนใจเกี่ยวกับคอลเลกชันที่ไม่เปลี่ยนรูปแบบทั่วไปและไม่ได้ทำนักพัฒนา Java ส่วนใหญ่ พวกเขาจะไม่สร้างลำดับชั้นของอินเทอร์เฟซทั้งหมดสำหรับคอลเลกชันที่ไม่เปลี่ยนรูปแล้วไม่รวมการใช้งานใด ๆ

บนมืออื่น ๆ ที่มีเพียงไม่กี่ค่าวัตถุประสงค์พิเศษหรือคอลเลกชัน "เสมือน" ที่อาจเป็นประโยชน์มากอย่างที่ไม่เปลี่ยนรูปเช่นเซตว่างและnCopies นอกจากนี้ยังมีคอลเลกชันที่ไม่เปลี่ยนรูปแบบของบุคคลที่สาม (เช่น Scala's) ซึ่งอาจต้องการเรียกรหัส Java ที่มีอยู่ดังนั้นพวกเขาจึงทิ้งความเป็นไปได้สำหรับคอลเลกชันที่ไม่เปลี่ยนรูปแบบที่เปิดในทางที่ก่อกวนน้อยที่สุด


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