क्लोन करने योग्य क्यों नहीं निकाला जाता है?


139

यह आमतौर पर समझा जाता है कि Cloneableजावा में इंटरफ़ेस टूट गया है। इसके कई कारण हैं, जिनका मैं उल्लेख नहीं करूंगा; दूसरों ने पहले ही कर दिया। यह जावा आर्किटेक्ट की भी स्थिति है स्वयं ।

मेरा प्रश्न इसलिए है: अभी तक क्यों नहीं निकाला गया है? यदि कोर जावा टीम ने तय किया है कि यह टूट गया है, तो उन्हें भी पदावनति पर विचार करना चाहिए। ऐसा करने के खिलाफ उनके कारण क्या हैं (जावा 8 में यह अभी भी पदावनत नहीं है )?


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

6
@MarkoTopolnik मैं मानता हूं कि दुनिया में कुछ ऐसे लोग हैं जो एक आधिकारिक उत्तर दे सकते हैं, लेकिन मुझे विश्वास नहीं है कि हम यहां जो परीक्षा लागू करते हैं। बंद कारण कहा गया है "इस प्रश्न के उत्तरों के लिए करते हैं जाएगा लगभग पूरी तरह से राय के आधार पर हो सकता है"। मुझे संदेह है कि यहां ऐसा ही होगा, जब तक कि हम बहुत भाग्यशाली नहीं हो जाते।
डंकन जोन्स

2
यहाँ ओरेकल से निकालने के लिए "कैसे और कब" है ... ( docs.oracle.com/javase/6/docs/technotes/guides/javadoc/… ) क्लोन करने योग्य इंटरफ़ेस "छोटी गाड़ी, या अत्यधिक अक्षम" मामले में पड़ सकता है लेकिन राय के लिए बहुत खुला है।
मैक्सएक्स

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

4
@lexicore हां, बिल्कुल --- और आप शर्त लगा सकते हैं कि उन्होंने पूरी तरह से उस विकल्प पर विचार किया है और निहितार्थ के पास इसे कम नहीं करने के मजबूत कारण होने चाहिए । उनकी अपनी आलोचना Cloneableव्यापक रूप से जानी जाती है।
मार्को टोपोलनिक

जवाबों:


120

1997 में जावा बग डेटाबेस में एक बग प्रस्तुत किया गया , जिसमें विधि को जोड़ने के बारे में बताया गया है , इसलिए यह अब बेकार नहीं होगा। इसे "ठीक नहीं होगा" प्रस्ताव के साथ बंद कर दिया गया था और औचित्य इस प्रकार था:clone()Cloneable

सन की तकनीकी समीक्षा समिति (टीआरसी) ने इस मुद्दे पर विचार किया और मौजूदा क्लोन इंटरफेस इंटरफ़ेस के प्रलेखन में सुधार के अलावा कोई कार्रवाई करने की सिफारिश की। । यहाँ सिफारिश का पूरा पाठ है:

मौजूदा जावा ऑब्जेक्ट क्लोनिंग एपीआई समस्याग्रस्त हैं। Java.lang.Object पर एक संरक्षित "क्लोन" विधि है और एक इंटरफ़ेस java.lang.Cloneable है। आशय यह है कि यदि कोई वर्ग अन्य लोगों को इसे क्लोन करने की अनुमति देना चाहता है, तो उसे क्लोन करने योग्य इंटरफ़ेस का समर्थन करना चाहिए और सार्वजनिक क्लोन विधि के साथ डिफ़ॉल्ट संरक्षित क्लोन विधि को ओवरराइड करना चाहिए। दुर्भाग्यवश, समय के मेल में आसानी से खो जाने वाले कारणों के लिए, क्लोन करने योग्य इंटरफ़ेस क्लोन पद्धति को परिभाषित नहीं करता है।

इस संयोजन से काफी मात्रा में भ्रम होता है। कुछ वर्ग क्लोन करने योग्य का समर्थन करने का दावा करते हैं, लेकिन गलती से क्लोन विधि का समर्थन करना भूल जाते हैं। डेवलपर्स उलझन में हैं कि क्लोन करने योग्य काम कैसे करना चाहिए और क्लोन क्या करना चाहिए।

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

एक वैकल्पिक प्रस्ताव एक नया इंटरफ़ेस java.lang.PubliclyCloneable जोड़ने के लिए क्लोन करने के मूल उद्देश्य को प्रतिबिंबित करने के लिए था। 5 से 2 बहुमत से, टीआरसी ने इसके खिलाफ सिफारिश की। मुख्य चिंता यह थी कि यह पहले से ही भ्रमित तस्वीर को और अधिक भ्रम (वर्तनी भ्रम सहित) जोड़ देगा।

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

इसलिए, भले ही यह नहीं है के बारे में सीधे पदावनत , Cloneable नहीं कर के लिए कारण "पदावनत" है तकनीकी समीक्षा Comitee फैसला किया है कि कि मौजूदा प्रलेखन संशोधित करने के लिए पर्याप्त पर्याप्त होगी इस इंटरफेस उपयोगी बनाने के लिए। और इसलिए उन्होंने किया। जावा 1.4 तक, Cloneableनिम्नानुसार प्रलेखित किया गया था:

एक क्लास ऑब्जेक्ट के लिए इंगित करने के लिए Cloneable इंटरफ़ेस को लागू करता है। विधि () विधि है कि यह उस वर्ग के उदाहरणों की फ़ील्ड-फॉर-फ़ील्ड प्रतिलिपि बनाने के लिए उस विधि के लिए कानूनी है।

क्लोन उदाहरणों के प्रयास जो क्लोन किए गए अपवाद CloneNotSupportedException में क्लोन करने योग्य इंटरफ़ेस परिणाम को लागू नहीं करते हैं।

इंटरफ़ेस क्लोन करने योग्य कोई विधि घोषित नहीं करता है।

जावा 1.4 (जिसे फरवरी 2002 में जारी किया गया था) वर्तमान संस्करण (जावा 8) तक यह इस तरह दिखता है:

एक क्लास ऑब्जेक्ट के लिए इंगित करने के लिए Cloneable इंटरफ़ेस को लागू करता है। विधि () विधि है कि यह उस वर्ग के उदाहरणों की फ़ील्ड-फॉर-फ़ील्ड प्रतिलिपि बनाने के लिए उस विधि के लिए कानूनी है। ऑब्जेक्ट के क्लोन विधि को एक ऐसे उदाहरण पर लागू करना, जो CloneNotSupportedException को अपवाद में फेंके जाने योग्य Cloneable इंटरफ़ेस परिणामों को लागू नहीं करता है।

सम्मेलन द्वारा, इस इंटरफ़ेस को लागू करने वाले वर्गों को एक सार्वजनिक विधि के साथ Object.clone (जो संरक्षित है) को ओवरराइड करना चाहिए। इस विधि को ओवरराइड करने के विवरण के लिए Object.clone () देखें।

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


3
और क्या आप जानते हैं कि cloneविधि Objectपहले स्थान पर क्यों थी?
njzk2

8
@ njzk2 यह तंत्र का एक अनिवार्य हिस्सा है - यह विधि है जो बिट-लेवल बिट के लिए ऑब्जेक्ट इमेज को कॉपी करने का निम्न-स्तर, प्रत्यर्पणात्मक जादू करता है।
मार्को टोपोलनिक

3
@Unheilig यह जादू एक ऐसी चीज है जिसे आप कॉपी कंस्ट्रक्टर के साथ नहीं दोहरा सकते हैं: Object#clone()उस वर्ग के बिना मूल के समान वर्ग का एक उदाहरण उत्पन्न करता है जिसे संकलन समय पर जाना जाता है।
मार्को टोपोलनिक

4
@AVolpe: जो उत्तर में उल्लिखित स्रोत की असंगति को ठीक नहीं करेगा "जहां कक्षाएं क्लोन करने योग्य इंटरफ़ेस का समर्थन करती हैं लेकिन सार्वजनिक क्लोन विधि प्रदान करने में विफल रहती हैं।" विशेष रूप से, गैर-गणतंत्र क्लोन पद्धति प्रदान करने वाली कक्षाएं टूट जाएंगी।
लुई वासरमैन

2
अच्छा इतिहास है। यहाँ बग डेटाबेस के लिए एक सीधा लिंक है। मैंने वहां कुछ और इतिहास जोड़ा है, और मैंने अपने उत्तर में इसके कुछ हिस्सों को उद्धृत किया है ।
स्टुअर्ट मार्क्स

64

"क्यों नहीं Cloneableनिकाला जाता है?" (या वास्तव में, Xकिसी के लिए पदावनत क्यों नहीं किया जाता हैX जाता है), यह है कि उन्हें पदावनत करने पर ज्यादा ध्यान नहीं दिया गया है।

हाल ही में हटाए गए अधिकांश चीजों को हटा दिया गया था क्योंकि उन्हें हटाने के लिए एक विशिष्ट योजना है। उदाहरण के लिए, LogManager के तरीकों addPropertyChangeListenerऔर removePropertyChangeListenerतरीकों को Java SE 8 में हटाने के इरादे से Java SE 8 में अपदस्थ किया गया था (इसका कारण यह है कि वे अनावश्यक रूप से जटिल अन्योन्याश्रित मॉड्यूल हैं।) दरअसल, इन APIs को पहले ही JDK 9 के विकास से हटा दिया गया है। बनाता है। (ध्यान दें कि समान संपत्ति परिवर्तन श्रोता कॉल को भी हटा दिया गया था Pack200; देखें JDK-8029806 ।)

ऐसा कोई समान योजना के लिए के लिए मौजूद है CloneableऔरObject.clone()

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

  • यह खतरनाक है और आप इसे का उपयोग कर के जोखिम के बारे में पता होना चाहिए (उदाहरण: Thread.stop(), Thread.resume(), और Thread.suspend())।

  • भविष्य में रिलीज़ में इसे हटा दिया जाएगा

  • यह अप्रचलित है और आपके लिए कुछ अलग उपयोग करना एक अच्छा विचार है (उदाहरण: कई विधियों में java.util.Date)

ये सभी अलग-अलग अर्थ हैं, और उनमें से अलग-अलग उपसमुच्चय अलग-अलग चीजों पर लागू होते हैं जो अपवित्र हैं। और उनमें से कुछ सबसेट उन चीजों पर लागू होते हैं जो अपवित्र नहीं होते हैं (लेकिन यह कि शायद पदावनत किया जाना चाहिए)।

Cloneableऔर Object.clone()इस अर्थ में "टूट" गए हैं कि उनके पास डिजाइन दोष हैं और सही ढंग से उपयोग करना मुश्किल है। हालांकि, clone()अभी भी सरणियों की नकल करने का सबसे अच्छा तरीका है, और क्लोनिंग में कक्षाओं के उदाहरणों की प्रतियां बनाने के लिए कुछ सीमित उपयोगिता है जो सावधानीपूर्वक कार्यान्वित की जाती हैं। क्लोनिंग को हटाना एक असंगत परिवर्तन होगा जो बहुत सारी चीजों को तोड़ देगा। एक क्लोनिंग ऑपरेशन को एक अलग तरीके से फिर से लागू किया जा सकता है, लेकिन यह शायद की तुलना में धीमा होगाObject.clone()

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

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

अपडेट करें

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

क्लोन करने योग्य के पास उसी कारण के लिए कोई विधि नहीं है जो Serializable नहीं करता है। क्लोन करने योग्य वर्ग की एक संपत्ति को इंगित करता है, बजाय विशेष रूप से उन तरीकों के बारे में कुछ भी कह रहा है जो वर्ग का समर्थन करता है।

प्रतिबिंब से पहले, हमें किसी वस्तु की उथली प्रतिलिपि बनाने के लिए एक देशी विधि की आवश्यकता होती है। इसलिए Object.clone () का जन्म हुआ। यह भी स्पष्ट था कि कई वर्ग इस पद्धति को ओवरराइड करना चाहेंगे, और यह कि हर वर्ग क्लोन नहीं बनाना चाहेगा। इसलिए प्रोग्रामर का इरादा इंगित करने के लिए क्लोन करने योग्य पैदा हुआ था।

तो, संक्षेप में। क्लोन करने योग्य का उद्देश्य यह बताना नहीं था कि आपके पास एक सार्वजनिक क्लोन () विधि है। यह इंगित करना था कि आप Object.clone () का उपयोग करके क्लोन किए जाने के लिए तैयार हैं, और यह क्लोन () सार्वजनिक करने के लिए तय करने के लिए कार्यान्वयन पर निर्भर था।


3
एक बढ़िया जवाब आपके पास है सर। मुझे विशेष रूप से यह पसंद है कि आप Object.clone()सिर्फ इसलिए आग में नहीं फेंकते हैं क्योंकि हर कोई चाहता है, लेकिन आप इसका कारण और अच्छी चीजों को लाना चाहते हैं।
icza

2
हालांकि, क्लोन () अभी भी सरणियों की नकल करने का सबसे अच्छा तरीका है, और क्लोनिंग के पास कक्षाओं के उदाहरणों की प्रतियों को बनाने के लिए कुछ सीमित उपयोगिता है जो सावधानीपूर्वक कार्यान्वित की जाती हैं। मैं 6428387 के फिक्स के साथ छापा था, सभी कोड पथ (क्लोन, नई / arrayCopy, Arrays.copyOf) के परिणामस्वरूप एक ही आंतरिक था। क्या हाल ही में कुछ बदला है?
bestsss

2
@bestsss मुझे नहीं लगता array.clone()कि किसी भी विकल्प की तुलना में तेजी से जरूरी है। एपीआई दृष्टिकोण से यह एक सरणी को डुप्लिकेट करने का सबसे संक्षिप्त तरीका है। Arrays.copyOf(array, newlen)करीब आता है, लेकिन इसके लिए एक लंबाई पैरामीटर की आवश्यकता होती है, जो यदि आप लंबाई नहीं बदल रहे हैं, तो यह बेमानी है।
स्टुअर्ट मार्क्स 23

2
@Holger हाँ जहाँ तक हम देख सकते हैं कि यह 1.1 के बाद से API की पहली वास्तविक निष्कासन है। ध्यान दें कि भले ही हम इस बात से सहमत हों कि Thread.suspend()और Thread.stop()(नहीं-अर्ग) खतरनाक हैं, उन्हें संभवतः हटाया नहीं जाएगा - या बिना किसी अपवाद के फेंकने के लिए बदल दिया - क्योंकि लोग वास्तव में उनका उपयोग करते हैं! संभवतः वे जोखिम उठाने को तैयार हैं। संपत्ति बदलने वाले श्रोताओं के साथ कम करने वाले कारकों में से एक यह है कि उनका उपयोग बहुत कम किया गया था, इसलिए उन्हें हटाने का प्रभाव छोटा है।
स्टुअर्ट मार्क्स

2
@ होल्गर वैचारिक java.beansरूप से स्वतंत्र किया जा सकता है java.desktopक्योंकि सेम गुणों के लिए सिर्फ एक पुस्तकालय एपीआई है। दुर्भाग्य से अगर आप सेम एपीआई में खुदाई करते हैं तो AWT पर बहुत सारी निर्भरताएं हैं। कार्यान्वयन और भी अधिक है। निश्चित रूप से उन्हें निकालना संभव हो सकता है, लेकिन ऐसा करना ऐसा लगता है कि सेम की तुलना में बहुत अधिक काम करना, कहना, असहमति देना। इस अव्यवस्था को करने के बारे में पूरा संशोधन प्रयास है; निस्संदेह अधिक किया जा सकता है, लेकिन तब आरा और भी अधिक समय लगेगा।
स्टुअर्ट मार्क्स

-1

इसे अभी तक क्यों नहीं हटाया गया?

क्योंकि JCP ने ऐसा करने के लिए फिट नहीं देखा है, और ऐसा कभी नहीं हो सकता है। उनसे पूछों। तुम गलत जगह पूछ रहे हो।

जावा एपीआई में इस बात को रखने के पीछे क्या कारण हैं

पीछे की संगतता की आवश्यकता के कारण जावा एपीआई से कोई भी कभी भी कुछ भी नहीं हटाएगा। आखिरी बार जो हुआ वह 1996/7 में 1.0 और 1.1 के बीच AWT इवेंट मॉडल में बदलाव था।


17
उन्होंने Thread.stop(Throwable)हमेशा के लिए अपने अनुबंध को बदलकर UnsupportedOperationExceptionकॉलर को फेंकने के लिए (प्रभावी रूप से हटा दिया ) (लक्ष्य धागे के लिए नहीं!)।
मार्को टोपोलनिक

22
उसी समय के आसपास क्या हुआ? Thread.stop(Throwable)जावा की कार्यक्षमता को हटाया जाना 8. वैसे भी, "उन्हें पूछने" की अयोग्य सलाह गलत है क्योंकि आज मुख्य जावा वास्तुकार स्वयं स्टैक ओवरफ्लो पर एक सक्रिय सदस्य है। वह सिर्फ कुछ भी लेकिन धाराओं से संबंधित सवालों के जवाब परेशान करने के लिए नहीं होता है।
मार्को टोपोलनिक

13
इसके अलावा, ओपी का सवाल हटाने के बारे में नहीं है , बल्कि पदावनति के बारे में है , और स्पष्ट रूप से पदावनति सभी के साथ हो रही है।
मार्को टोपोलनिक

17
@EJP मैं यह नहीं पूछ रहा हूं कि क्या Cloneableजावा एपीआई से हटाया जाएगा। मैं पूछ रहा हूं कि क्यों यह विचलित नहीं होने वाला है। और मुझे लगता है कि यह पूछने के लिए एक सही जगह है।
काओ

5
@VaHHarutyunyan चिल्लाओ-आउट के लिए धन्यवाद, लेकिन मैं जावा वास्तुकार नहीं हूं। मैं ओरेकल के जेडीके समूह में एक इंजीनियर हूं, जो इस सामान को बनाए रखता है।
स्टुअर्ट मार्क्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.