जावा क्लोन के बारे में


95

मैं जावा के बारे में समझाते हुए कुछ ट्यूटोरियल खोज रहा था Cloneable, लेकिन कोई भी अच्छा लिंक नहीं मिला, और स्टैक ओवरफ्लो वैसे भी अधिक स्पष्ट विकल्प बन रहा है।

मैं निम्नलिखित जानना चाहूंगा:

  1. Cloneableइसका मतलब है कि हम Cloneableइंटरफ़ेस को लागू करके एक क्लोन या वस्तुओं की एक प्रति हो सकते हैं । ऐसा करने के क्या फायदे और नुकसान हैं?
  2. यदि वस्तु एक समग्र वस्तु है तो पुनरावर्ती क्लोनिंग कैसे होती है?

2
क्या की तुलना में फायदे और नुकसान?
गैलेक्टस

4
मैंने पढ़ा है कि एक वर्ग के लाभ का मतलब है Cloneable बनाम नहीं। निश्चित नहीं है कि और कैसे व्याख्या की जा सकती है: एस
एलोयूरकोड

जवाबों:


159

पहली चीज जिसके बारे Cloneableमें आपको पता होना चाहिए वह है - इसका उपयोग न करना।

Cloneableसही के साथ क्लोनिंग को लागू करना बहुत कठिन है , और प्रयास इसके लायक नहीं है।

इसके बजाय कुछ अन्य विकल्पों का उपयोग करें, जैसे अपाचे-कॉमन्स SerializationUtils(डीप-क्लोन) या BeanUtils(उथले-क्लोन), या बस कॉपी-कंस्ट्रक्टर का उपयोग करें।

यहां देखें जोश ब्लोच के विचारों के साथ क्लोनिंग के बारे में Cloneable, जो दृष्टिकोण की कई कमियां बताते हैं। ( यहोशू बलोच एक सूर्य कर्मचारी था, और कई जावा सुविधाओं के विकास का नेतृत्व किया।)


1
मैंने बलोच के शब्दों (उन्हें उद्धृत करने के बजाय) को
जोड़ा

3
ध्यान दें कि ब्लॉक का कहना है कि क्लोन करने योग्य का उपयोग न करें। वह कहते हैं कि क्लोनिंग का उपयोग न करें (या कम से कम मुझे आशा नहीं है)। क्लोनिंग को लागू करने के कई तरीके हैं जो कि SerializationUtils या BeanUtils जैसी कक्षाओं की तुलना में कहीं अधिक कुशल हैं जो प्रतिबिंब का उपयोग करते हैं। एक उदाहरण के लिए नीचे मेरी पोस्ट देखें।
चार्ल्स

इंटरफेस को परिभाषित करते समय एक कॉपी कंस्ट्रक्टर का विकल्प क्या है? बस एक कॉपी विधि जोड़ें?
बेनेज़

@ बेनेज़ मैं हाँ कहूँगा। जावा -8 के बाद से आपके पास staticइंटरफेस में तरीके हो सकते हैं , इसलिए बस एक प्रदान करें static WhatEverTheInterface copy(WhatEverTheInterface initial)? लेकिन मुझे आश्चर्य है कि यह आपको क्या देता है, क्योंकि आप क्लोनिंग करते समय किसी ऑब्जेक्ट से फ़ील्ड कॉपी करते हैं, लेकिन एक इंटरफ़ेस केवल तरीकों को परिभाषित करता है। समझाने की परवाह?
यूजीन

40

क्लोन करने योग्य स्वयं दुर्भाग्य से एक मार्कर-इंटरफ़ेस है, अर्थात: यह क्लोन () विधि को परिभाषित नहीं करता है।

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

यहां तक ​​कि अगर यह वह व्यवहार है जिसे आप ढूंढ रहे हैं, तब भी आपको इसे सार्वजनिक करने के लिए अपने स्वयं के क्लोन () विधि को लागू करने की आवश्यकता होगी।

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

यह दृष्टिकोण किसी भी तर्क को दरकिनार कर देता है जिसे आपके निर्माणकर्ताओं में परिभाषित किया जा सकता है, जो संभावित रूप से समस्याग्रस्त हो सकता है।

एक और समस्या यह है कि कोई भी उपवर्ग जो क्लोन () को ओवरराइड करना भूल जाता है, स्वतः ही डिफॉल्ट उथले कॉपी को इनहेरिट कर देगा, जो संभवत: वह नहीं है जो आप उत्परिवर्तित होने की स्थिति में चाहते हैं (जो अब स्रोत और कॉपी के बीच साझा किया जाएगा)।

अधिकांश डेवलपर्स इन कारणों से क्लोन करने योग्य का उपयोग नहीं करते हैं, और इसके बजाय बस एक कॉपी कंस्ट्रक्टर को लागू करते हैं।

Cloneable की अधिक जानकारी और संभावित नुकसान के लिए, मैं अत्यधिक यहोशू बलोच द्वारा प्रभावी जावा पुस्तक की सिफारिश करता हूं


12
  1. क्लोनिंग ऑब्जेक्ट्स के निर्माण के बिना - बिल्डरों के एक अतिरिक्त-भाषाई तरीके को लागू करता है।
  2. क्लोनिंग के लिए आपको किसी तरह से CloneNotSupportedException के साथ इलाज करने की आवश्यकता होती है - या इसके इलाज के लिए क्लाइंट कोड को परेशान करने के लिए।
  3. लाभ छोटे हैं - आपको बस एक कॉपी करने वाले कंस्ट्रक्टर को मैन्युअल रूप से लिखना नहीं है।

तो, Cloneable का उपयोग विवेकपूर्ण तरीके से करें। यह आपको उस प्रयास की तुलना में पर्याप्त लाभ नहीं देता है जो आपको सब कुछ सही करने के लिए लागू करने की आवश्यकता है।


जैसा कि Bozho ने कहा, Cloneable का उपयोग न करें। इसके बजाय, कॉपी-कंस्ट्रक्टर का उपयोग करें। javapractices.com/topic/TopicAction.do?Id=12
बने

@, यदि आप क्लोन करने के लिए ऑब्जेक्ट के प्रकार को नहीं जानते हैं, तो आप कैसे जानेंगे कि किस क्लास के कॉपी कंस्ट्रक्टर को इनवाइट करना है?
स्टीव कुओ

@ साइट: मैं अनुसरण नहीं करता। यदि आप किसी ऑब्जेक्ट को क्लोन करने जा रहे हैं, तो मुझे लगता है कि आप पहले से ही जानते हैं कि यह किस प्रकार का है - आखिरकार, आपके पास इन-हैंड वस्तु है जिसे आप क्लोन करने की योजना बना रहे हैं। और अगर कोई ऐसी स्थिति है जहां आपकी वस्तु खो गई है तो यह विशिष्ट-प्रकार से अधिक सामान्य है, क्या आप इसे एक सरल 'उदाहरण' का उपयोग करके मूल्यांकन नहीं कर सकते हैं ???
बैन

4
@ बैन: मान लीजिए कि आपके पास ए, 10 प्रकार के विभिन्न प्रकारों से प्राप्त वस्तुओं की एक सूची है। आप नहीं जानते कि प्रत्येक वस्तु का प्रकार क्या है। इस मामले में Instof का उपयोग करना एक बहुत बुरा विचार है। यदि आप एक और प्रकार जोड़ते हैं, तो हर बार जब आप ऐसा करते हैं, तो आपको एक और इंस्टाफॉ़ड टेस्ट जोड़ना होगा। और, क्या होगा अगर व्युत्पन्न वर्ग एक और पैकेज में हैं जो आप एक्सेस भी नहीं कर सकते हैं? क्लोनिंग एक सामान्य पैटर्न है। हां, जावा कार्यान्वयन खराब है, लेकिन इसके आसपास कई तरीके हैं जो ठीक काम करेंगे। एक कॉपी कंस्ट्रक्टर एक समकक्ष ऑपरेशन नहीं है।
चार्ल्स

@Charles: एक विस्तृत-उदाहरण के अभाव में, और इस तरह की समस्या से निपटने के लिए हाल के अनुभव की कमी के कारण, मुझे बलोच के पास जाना होगा। आइटम # 11। यह लंबा और थोड़ा कठिन पढ़ा गया है, लेकिन यह मूल रूप से कहता है "जब भी आप कर सकते हैं क्लोन से बचें, कॉपी कंस्ट्रक्टर आपके दोस्त हैं"।
बैन

7

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

मान लीजिए कि मेरे पास ए, बी, और सी की कक्षाएं हैं, जहां बी और सी ए से प्राप्त होते हैं। यदि मेरे पास इस प्रकार की वस्तुओं की सूची है:

ArrayList<A> list1;

अब, उस सूची में ए, बी या सी प्रकार की वस्तुएं हो सकती हैं। आप नहीं जानते कि वस्तुएं किस प्रकार की हैं। इसलिए, आप सूची को इस तरह से कॉपी नहीं कर सकते हैं:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(new A(a));
}

यदि वस्तु वास्तव में बी या सी प्रकार की है, तो आपको सही कॉपी नहीं मिलेगी। और, क्या होगा अगर A सार है? अब, कुछ लोगों ने यह सुझाव दिया है:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    if(a instanceof A) {
        list2.add(new A(a));
    } else if(a instanceof B) {
        list2.add(new B(a));
    } else if(a instanceof C) {
        list2.add(new C(a));
    }
}

यह एक बहुत ही बुरा विचार है। यदि आप एक नया व्युत्पन्न प्रकार जोड़ते हैं तो क्या होगा? क्या होगा यदि बी या सी किसी अन्य पैकेज में हैं और आपके पास इस कक्षा में उनकी पहुंच नहीं है?

आप यह करना चाहते हैं:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(a.clone());
}

बहुत से लोगों ने संकेत दिया है कि क्लोन का मूल जावा कार्यान्वयन समस्याग्रस्त क्यों है। लेकिन, यह आसानी से इस तरह से दूर हो जाएगा:

कक्षा ए में:

public A clone() {
    return new A(this);
}

कक्षा B में:

@Override
public B clone() {
    return new B(this);
}

कक्षा सी में:

@Override
public C clone() {
    return new C(this):
}

मैं Cloneable को लागू नहीं कर रहा हूं, बस एक ही फ़ंक्शन नाम का उपयोग कर रहा हूं। यदि आपको यह पसंद नहीं है, तो इसे कुछ और नाम दें।


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

हालांकि मैं यह कहना चाहता हूं कि मैं आपके दृष्टिकोण से सहमत हूं, जिसमें ए # copyMethod () शामिल है, बजाय इसके कि उपयोगकर्ता को सीधे कॉपी-कंस्ट्रक्टर को कॉल करने के लिए मजबूर किया जाए।
बैन

5

ए) एक कॉपी कंस्ट्रक्टर पर क्लोन के पूरे बहुत सारे फायदे नहीं हैं। संभवतः सबसे बड़ा एक ही समान गतिशील प्रकार का एक नया ऑब्जेक्ट बनाने की क्षमता है (घोषित प्रकार को क्लोन करना और सार्वजनिक क्लोन विधि है)।

बी) डिफ़ॉल्ट क्लोन एक उथली प्रतिलिपि बनाता है, और यह एक उथली प्रतिलिपि बना रहेगा जब तक कि आपके क्लोन कार्यान्वयन में परिवर्तन न हो। यह मुश्किल हो सकता है, खासकर यदि आपकी कक्षा में अंतिम क्षेत्र हैं

बोझो सही है, क्लोन सही होना मुश्किल हो सकता है। एक कॉपी कंस्ट्रक्टर / फैक्ट्री सबसे ज्यादा जरूरतें पूरी करेगा।


0

क्लोन करने योग्य के नुकसान क्या हैं?

क्लोनिंग बहुत खतरनाक है यदि आप जिस वस्तु की नकल कर रहे हैं, उसकी रचना है। आपको इस मामले में संभावित दुष्प्रभावों के बारे में नीचे सोचने की आवश्यकता है क्योंकि क्लोन उथले प्रतिलिपि बनाता है:

मान लें कि आपके पास db संबंधित हेरफेर को संभालने के लिए एक ऑब्जेक्ट है। कहो, वह वस्तु हैConnection में एक संपत्ति के रूप वस्तु है।

इसलिए जब कोई व्यक्ति क्लोन बनाता है originalObject, तो ऑब्जेक्ट बनाया जा रहा है, कहने दो cloneObject। यहाँ originalObjectऔर के cloneObjectलिए एक ही संदर्भ पकड़ोConnection वस्तु।

मान लें कि ऑब्जेक्ट originalObjectबंद हो गया Connectionहै, इसलिए अब cloneObjectयह काम नहीं करेगा क्योंकि connectionऑब्जेक्ट उनके बीच साझा किया गया था और यह एक्ट्यूएली द्वारा बंद कर दिया गया थाoriginalObject

इसी तरह की समस्या तब हो सकती है यदि आप कहते हैं कि आप एक ऑब्जेक्ट को क्लोन करना चाहते हैं जिसके पास संपत्ति के रूप में IOStream है।

यदि वस्तु एक समग्र वस्तु है तो पुनरावर्ती क्लोनिंग कैसे होती है?

क्लोन करने योग्य उथली प्रति करता है। अर्थ यह है कि मूल वस्तु और क्लोन ऑब्जेक्ट का डेटा एक ही संदर्भ / मेमोरी को इंगित करेगा। गहरी प्रतिलिपि के मामले में, मूल ऑब्जेक्ट की मेमोरी से डेटा क्लोन ऑब्जेक्ट की मेमोरी में कॉपी किया जाता है।


आपका अंतिम पैराग्राफ बहुत उलझन में है। Cloneableएक प्रति प्रदर्शन नहीं करता है, Object.cloneकरता है। "मूल ऑब्जेक्ट की मेमोरी से डेटा को क्लोन ऑब्जेक्ट की मेमोरी में कॉपी किया जाता है" ठीक यही Object.cloneकरता है। आपको गहरी नकल का वर्णन करने के लिए संदर्भित वस्तुओं की स्मृति के बारे में बात करने की आवश्यकता है।
aioobe
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.