जावा संग्रह ढांचे के इंटरफेस में UnsupportedOperationException


12

जावा कलेक्शंस फ्रेमवर्क के माध्यम से, मैंने देखा है कि कुछ इंटरफेस में टिप्पणी है (optional operation)। इन विधियों के माध्यम से कक्षाओं को लागू करने की अनुमति देता है UnsupportedOperationExceptionयदि वे सिर्फ उस पद्धति को लागू नहीं करना चाहते हैं।

इसका एक उदाहरण addAllविधि है Set Interface

अब, जैसा कि सवालों की इस श्रृंखला में कहा गया है, इंटरफेस इस बात के लिए एक परिभाषित अनुबंध है कि उपयोग क्या उम्मीद कर सकता है।

इंटरफेस महत्वपूर्ण हैं क्योंकि वे अलग करते हैं कि कोई वर्ग यह कैसे करता है। एक ग्राहक क्या उम्मीद कर सकता है यह अनुबंध को परिभाषित करता है कि डेवलपर किसी भी तरह से इसे लागू करने के लिए स्वतंत्र छोड़ सकता है, जब तक वे अनुबंध को बनाए रखते हैं।

तथा

एक इंटरफ़ेस उन क्रियाओं का वर्णन है जो एक वस्तु कर सकती है ... उदाहरण के लिए जब आप एक प्रकाश स्विच को फ्लिप करते हैं, तो प्रकाश चलता है, आप परवाह नहीं करते कि कैसे, बस यही करता है। ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में, एक इंटरफ़ेस सभी कार्यों का वर्णन है जो एक ऑब्जेक्ट को "एक्स" होने के लिए होना चाहिए।

तथा

मुझे लगता है कि इंटरफ़ेस-आधारित दृष्टिकोण काफी अच्छा है। फिर आप अपनी निर्भरता का अच्छी तरह से मजाक उड़ा सकते हैं, और सब कुछ मूल रूप से कम कसकर युग्मित है।

एक इंटरफेस का क्या मतलब है?

इंटरफेस क्या हैं?

इंटरफ़ेस + एक्सटेंशन (मिक्सिन) बनाम बेस क्लास

यह देखते हुए कि इंटरफेस का उद्देश्य एक अनुबंध को परिभाषित करना और अपनी निर्भरता को शिथिल करना है, कुछ तरीकों UnsupportedOperationExceptionसे उद्देश्य को हराने का एक तरीका नहीं है? इसका मतलब है कि मैं अब पारित नहीं किया जा सकता है Setऔर सिर्फ उपयोग कर सकता हूं addAll। बल्कि, मुझे यह जानना होगा कि Setमैं किस कार्यान्वयन को पारित किया गया था, इसलिए मुझे पता चल सकता है कि मैं उपयोग कर सकता हूं addAllया नहीं। यह मुझे बहुत बेकार लगता है।

तो देर किस बात की UnsupportedOperationException? क्या यह सिर्फ विरासत कोड के लिए बना रहा है, और उन्हें अपने इंटरफेस को साफ करने की आवश्यकता है? या यह एक अधिक सनसनीखेज उद्देश्य है जो मुझे याद आ रहा है?


मुझे नहीं पता कि आप किस JRE का उपयोग कर रहे हैं, लेकिन मेरा Oracle संस्करण 8 addAllमें परिभाषित नहीं है HashSet। यह डिफॉल्ट कार्यान्वयन पर निर्भर AbstractCollectionकरता है जिसमें सबसे निश्चित रूप से फेंक नहीं हैUnsupportedOperationException

@Snowman तुम सही हो। मुझे डॉक्स की याद आती है। मैं अपने प्रश्न का संपादन करूंगा।
दर्पण

1
मुझे ग्रहण शुरू करने और स्रोत कोड को देखने के लिए पसंद है, कोड संदर्भ और परिभाषाओं के आसपास उछलते हुए यह सुनिश्चित करने के लिए कि मेरे पास यह सही है। जब तक जेआरई से जुड़ा हुआ है src.zipतब तक बढ़िया काम करता है। यह जानने में मदद करता है कि जेआरई कभी-कभी किस कोड को चला रहा है और JavaDoc को स्थगित नहीं करता है जो कि थोड़ा वर्बोज़ हो सकता है।

जवाबों:


12

निम्नलिखित इंटरफेस देखें:

ये सभी परिवर्तनशील तरीकों को वैकल्पिक घोषित करते हैं । यह इस तथ्य को स्पष्ट रूप से प्रलेखित कर रहा है कि संग्रह वर्ग उन इंटरफेस के कार्यान्वयन को वापस करने में सक्षम है जो अपरिवर्तनीय हैं: अर्थात्, उन वैकल्पिक म्यूटेशन कार्यों को विफल करने की गारंटी है। हालांकि, JavaDoc में अनुबंध के अनुसार, उन इंटरफेस के सभी कार्यान्वयनों को पढ़ने के संचालन की अनुमति देनी चाहिए। इसमें "सामान्य" कार्यान्वयन HashSetऔर LinkedListसाथ ही अपरिवर्तनीय आवरण शामिल हैं Collections

कंट्रास्ट इंटरफेस के साथ कंट्रास्ट:

ये इंटरफ़ेस किसी भी वैकल्पिक संचालन को निर्दिष्ट नहीं करते हैं: एक कतार, परिभाषा के अनुसार, एक FIFO तरीके से और तत्वों को प्रदूषित करने के लिए डिज़ाइन किया गया है। एक अपरिवर्तनीय कतार पहियों के बिना कार के रूप में उपयोगी है।


एक सामान्य विचार जो बार-बार सामने आता है वह एक वंशानुगत पदानुक्रम होता है जिसमें परस्पर और अपरिवर्तनीय दोनों प्रकार की वस्तुएँ होती हैं। हालांकि, इन सभी में कमियां हैं। जटिलता वास्तव में समस्या को हल किए बिना पानी को पिघलाती है।

  • एक काल्पनिक Setपढ़ने के संचालन हो सकता है, और एक उपप्रकार MutableSetलेखन कार्य हो सकता है। Liskov हमें बताता है कि एक के MutableSetलिए कुछ भी पारित किया जा सकता है कि एक की जरूरत है Set। पहली बार में यह ठीक लगता है, लेकिन एक विधि पर विचार करें जो पढ़ते समय अंतर्निहित सेट को संशोधित नहीं किया जाएगा: दो थ्रेड्स के लिए एक ही सेट का उपयोग करना संभव होगा और सेट के अपरिवर्तनीय का उल्लंघन न करें। यह एक समस्या का कारण बन सकता है जैसे अगर कोई विधि दो बार सेट से एक तत्व पढ़ती है और यह पहली बार है, लेकिन दूसरी बार नहीं।

  • Setइसके बाद कोई सीधा कार्यान्वयन नहीं हो सकता है, इसके बजाय MutableSetऔर ImmutableSetउप-केंद्रों के रूप में जो तब वर्गों को लागू करने के लिए उपयोग किया जाता है। यह ऊपर के रूप में एक ही मुद्दा है: पदानुक्रम में कुछ बिंदु पर, एक इंटरफ़ेस में परस्पर विरोधी हमलावर होते हैं। एक कहता है "यह सेट परस्पर होना चाहिए" और दूसरा कहता है "यह सेट नहीं बदल सकता है।"

  • परिवर्तनशील और अपरिवर्तनीय डेटा संरचनाओं के लिए दो पूरी तरह से अलग पदानुक्रम हो सकते हैं। यह अतिरिक्त जटिलता का एक टन जोड़ता है जिसके लिए बहुत कम लाभ होता है। इसमें उन विधियों की विशिष्ट कमजोरी भी है जो उत्परिवर्तन के बारे में परवाह नहीं करते हैं (जैसे मैं केवल एक सूची को पुनरावृत्त करना चाहता हूं) को अब दो आवश्यक इंटरफेस का समर्थन करना चाहिए। चूंकि Java वैधानिक रूप से टाइप किया गया है, इसका मतलब दोनों इंटरफ़ेस पदानुक्रमों को संभालने के लिए अतिरिक्त तरीके हैं।

  • हमारा एक ही इंटरफ़ेस हो सकता है और यदि कोई विधि उस पर लागू नहीं होती है तो अपवादों को लागू करने की अनुमति दे सकती है। यह वह मार्ग है जिसे जावा ने लिया था, और यह सबसे अधिक समझ में आता है। इंटरफेस की संख्या को न्यूनतम रखा गया है, और कोई पारस्परिकता अपरिवर्तनीय नहीं हैं, क्योंकि दस्तावेज़ित इंटरफ़ेस इस तरह से परिवर्तनशीलता के बारे में कोई गारंटी नहीं देता है । यदि एक अपरिवर्तनीयता अपरिवर्तनीय आवश्यक है, तो रैपरों का उपयोग करें Collections। यदि किसी विधि को किसी संग्रह को बदलने की आवश्यकता नहीं है, तो बस उसे परिवर्तित न करें। दोष यह है कि एक विधि गारंटी नहीं दे सकती कि एक संग्रह दूसरे धागे में नहीं बदलेगा यदि उसे बाहर से संग्रह प्रदान किया जाता है, लेकिन यह वैसे भी कॉलिंग विधि (या इसकी कॉलिंग विधि) की चिंता है।


संबंधित पढ़ने: क्यों जावा 8 अपरिवर्तनीय संग्रह शामिल नहीं है?


1
लेकिन अगर विधियां वैकल्पिक हैं, तो उनके पास इंटरफ़ेस में कौन सी जगह है? उदाहरण के लिए, वैकल्पिक तरीकों वाले एक अलग इंटरफ़ेस नहीं होना चाहिए MutableCollection?
दर्पण

नहीं। किसी भी सार्थक तरीके से एक ही पदानुक्रम में परस्पर और अपरिवर्तनीय वस्तुओं को रखने का कोई तरीका नहीं है। हाल ही में एक सवाल था जिसमें एक अच्छा आरेख था जो जटिलता दिखा रहा था और एक स्पष्टीकरण था कि यह एक बुरा विचार क्यों है, लेकिन इसे हटा दिया गया है। शायद किसी और को यह समझाने में मदद करने के लिए एक सवाल का पता है, मुझे कुछ भी नहीं मिल रहा है। लेकिन मैं अपने उत्तर को थोड़ा समझाने के लिए अपडेट करूंगा।

अपरिवर्तनीय कतारों के बारे में यह एक व्यापक कथन है। मैं प्रयोग किया जाता है एक बस कुछ ही दिन पहले हल करने के लिए इस समस्या को
कार्ल बेज़ेलफेल्ट

@Snowman लेकिन ऐसा लगता है कि एक दूसरे के विपरीत के रूप में उस परस्पर और अपरिवर्तनीय वस्तुओं को बनाने के लिए। मुझे लगता है कि अपरिवर्तनीय वस्तु वास्तव में सिर्फ वस्तुओं को बदलने की क्षमता की कमी है। ईमानदारी से, यह अभी जिस तरह से है वह अधिक जटिल और अस्पष्ट है, क्योंकि आपको यह पता लगाना होगा कि एक परस्पर कार्यान्वयन क्या है और क्या नहीं है। मुझे लगता है कि सभी तरीकों को एक इंटरफ़ेस में रखने के बीच एकमात्र अंतर यह है कि उत्परिवर्तनीय तरीकों को विभाजित करने का विरोध स्पष्टता में से एक है।
दर्पण

@MirroredFate ने मेरा सबसे हाल का संपादन पढ़ा।

2

यह मूल रूप से YAGNI है। मानक लाइब्रेरी में सभी ठोस संग्रह वैकल्पिक संचालन को लागू करने या इनहेरिट करने योग्य हैं। वे सामान्य उद्देश्य अपरिवर्तनीय संग्रह के बारे में परवाह नहीं करते हैं और न ही जावा डेवलपर्स के विशाल बहुमत को करते हैं। वे पूरी तरह से संग्रहणीय संग्रह के लिए संपूर्ण इंटरफ़ेस पदानुक्रम बनाने नहीं जा रहे हैं, फिर कोई भी कार्यान्वयन शामिल नहीं है।

दूसरी ओर, कुछ विशेष-उद्देश्य मूल्य या "आभासी" संग्रह हैं जो अपरिवर्तनीय के रूप में बहुत उपयोगी हो सकते हैं, जैसे कि खाली सेट , और nCopies । इसके अलावा, तीसरे पक्ष के अपरिवर्तनीय संग्रह (जैसे स्काला के) हैं, जो मौजूदा जावा कोड को कॉल करना चाह सकते हैं, इसलिए उन्होंने अपरिवर्तनीय संग्रह की संभावना को कम से कम विघटनकारी तरीके से खोल दिया।


ठीक है, यह कुछ समझ में आता है। यह अभी भी ऐसा लगता है कि यह गलत दिशा से समस्या का सामना करता है, हालांकि। अपरिवर्तनीय संग्रह इंटरफेस को परिभाषित करने से शुरू क्यों नहीं किया जाता है, और फिर उत्परिवर्तनीय संग्रह कार्यान्वयन के लिए परस्पर अंतर को परिभाषित करते हैं?
शीशे का
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.