2009-01-24 8 views
17

मेरे पास एक ऑब्जेक्ट है जिसे मुझे जावा में कॉपी करने की आवश्यकता है। मुझे मूल प्रतिलिपि को बदले बिना एक प्रतिलिपि बनाने और कुछ परीक्षण चलाने की आवश्यकता है।जावा में किसी ऑब्जेक्ट की प्रतिलिपि बनाएँ

मुझे लगता है कि मुझे क्लोन() विधि का उपयोग करने की आवश्यकता है, लेकिन यह संरक्षित है। नेट पर कुछ शोध करने के बाद, मैं देख सकता हूं कि यह मेरी कक्षा में सार्वजनिक विधि से अधिक हो सकता है। लेकिन मुझे यह कैसे करना है इस बारे में कोई स्पष्टीकरण नहीं मिल रहा है। यह कैसे किया जा सकता है?

इसके अलावा, क्या मुझे यह आवश्यक करने का सबसे अच्छा तरीका है?

+0

पर समर्थित है है इस परीक्षण उद्देश्य केवल (इकाई-परीक्षण) के लिए, या क्या आपको वास्तविक उत्पादन कोड में इस कार्यक्षमता की आवश्यकता है? – crunchdog

उत्तर

13

कुछ विकल्प:

  • आप अपने वस्तु के लिए Cloneable को लागू करने और सार्वजनिक रूप clone() विधि डाल सकते हैं। यहां पूर्ण स्पष्टीकरण देखें: http://www.cafeaulait.org/course/week4/46.html
    हालांकि, यह एक उथली प्रतिलिपि बनाता है और ऐसा कुछ नहीं हो सकता है जो आप चाहते हैं।
  • आप अपनी वस्तु को क्रमबद्ध और deserialize कर सकते हैं। ऑब्जेक्ट और उसके सभी फ़ील्ड के लिए आपको Serializable इंटरफ़ेस को लागू करने की आवश्यकता होगी।
  • आप XML के माध्यम से क्रमबद्ध करने के लिए XStream का उपयोग कर सकते हैं - आपको यहां कुछ भी लागू करने की आवश्यकता नहीं है।
7

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

27

कॉपी निर्माता का उपयोग कर (Java Practices से) द्वारा एक अन्य विकल्प:

public final class Galaxy { 

    public Galaxy (double aMass, String aName) { 
     fMass = aMass; 
     fName = aName; 
    } 

    /** 
    * Copy constructor. 
    */ 
    public Galaxy(Galaxy aGalaxy) { 
     this(aGalaxy.getMass(), aGalaxy.getName()); 
     //no defensive copies are created here, since 
     //there are no mutable object fields (String is immutable) 
    } 

    /** 
    * Alternative style for a copy constructor, using a static newInstance 
    * method. 
    */ 
    public static Galaxy newInstance(Galaxy aGalaxy) { 
     return new Galaxy(aGalaxy.getMass(), aGalaxy.getName()); 
    } 

    public double getMass() { 
     return fMass; 
    } 

    /** 
    * This is the only method which changes the state of a Galaxy 
    * object. If this method were removed, then a copy constructor 
    * would not be provided either, since immutable objects do not 
    * need a copy constructor. 
    */ 
    public void setMass(double aMass){ 
     fMass = aMass; 
    } 

    public String getName() { 
     return fName; 
    } 

    // PRIVATE ///// 
    private double fMass; 
    private final String fName; 

    /** 
    * Test harness. 
    */ 
    public static void main (String... aArguments){ 
     Galaxy m101 = new Galaxy(15.0, "M101"); 

     Galaxy m101CopyOne = new Galaxy(m101); 
     m101CopyOne.setMass(25.0); 
     System.out.println("M101 mass: " + m101.getMass()); 
     System.out.println("M101Copy mass: " + m101CopyOne.getMass()); 

     Galaxy m101CopyTwo = Galaxy.newInstance(m101); 
     m101CopyTwo.setMass(35.0); 
     System.out.println("M101 mass: " + m101.getMass()); 
     System.out.println("M101CopyTwo mass: " + m101CopyTwo.getMass()); 
    } 
} 
+4

मैं कॉपी कन्स्ट्रक्टर में गेटर का उपयोग नहीं करता। सबसे पहले आपको उनकी आवश्यकता नहीं है क्योंकि आप हमेशा आवृत्ति चर तक पहुंच सकते हैं। दूसरा यदि आप इसे स्वयं एक अभ्यास करते हैं तो आप बहुत अधिक गेटर्स बनाकर encapsulation कम कर सकते हैं। और अंत में यह त्रुटि प्रवण हो सकता है। कल्पना करें कि आप getMass() में मान को ट्विक करें, आप नए ऑब्जेक्ट के इंस्टेंस वैरिएबल में tweaked वैल्यू की प्रतिलिपि बना लेंगे, यदि आप दूसरी ऑब्जेक्ट पर getMass को कॉल करते हैं तो दूसरी बार मान को ट्विक कर देगा। –

+0

@Mr_and_Mrs_D, आप सही हैं - मैंने इसे पहले पढ़ने पर नहीं देखा था। नॉरबर्ट का मुद्दा अभी भी खड़ा है। –

1

यहोशू बलोच some interesting things to say about cloneable है। ऑब्जेक्ट के आकार/निर्माण के आधार पर, मैं ऊपर उल्लिखित समाधानों में से किसी एक का उपयोग करके ऑब्जेक्ट में एक कॉपी कन्स्ट्रक्टर, या सीरियल/deserialise जोड़ना होगा।

20

दो लोकप्रिय दृष्टिकोण हैं। एक जैसा कि आपने उल्लेख किया है, clone विधि प्रदान करना है।

public class C implements Cloneable { 
    @Override public C clone() { 
     try { 
      final C result = (C) super.clone(); 
      // copy fields that need to be copied here! 
      return result; 
     } catch (final CloneNotSupportedException ex) { 
      throw new AssertionError(); 
     } 
} 

"कॉपी फ़ील्ड ... यहां पर ध्यान दें!" अंश। प्रारंभिक result केवल एक उथली प्रतिलिपि है, जिसका अर्थ है कि यदि किसी ऑब्जेक्ट का संदर्भ है, तो मूल और result दोनों एक ही ऑब्जेक्ट को साझा करेंगे। उदाहरण के लिए, यदि C में private int[] data है तो आप शायद इसकी प्रतिलिपि बनाना चाहते हैं।

... 
final C result = (C) super.clone(); 
result.data = data.clone(); 
return result; 
... 

ध्यान दें कि आप आदिम क्षेत्रों कॉपी करने के लिए, के रूप में अपनी सामग्री को पहले से ही नकल की जाती है या अपरिवर्तनीय वस्तुओं, वे वैसे भी नहीं बदल सकते हैं के रूप में की जरूरत नहीं है।

दूसरा दृष्टिकोण प्रतिलिपि बनाने वाला है।

public class C { 
    public C(final C c) { 
     // initialize this with c 
    } 
} 

या एक प्रति कारखाना।

public class C { 
    public static C newInstance(final C c) { 
     return new C(c); 
    } 

    private C(final C c) { 
     // initialize this with c 
    } 
} 

दोनों दृष्टिकोणों के पास उनके संबंधित गुण हैं। clone अच्छा है क्योंकि इसकी एक विधि है, इसलिए आपको सटीक प्रकार को जानने की आवश्यकता नहीं है। अंत में, आपको हमेशा "परिपूर्ण" प्रतिलिपि के साथ समाप्त होना चाहिए। कॉपी कन्स्ट्रक्टर अच्छा है क्योंकि कॉलर को निर्णय लेने का मौका है, जैसा कि जावा कलेक्शन द्वारा देखा जा सकता है।

final List c = ... 
// Got c from somewhere else, could be anything. 
// Maybe too slow for what we're trying to do? 

final List myC = new ArrayList(c); 
// myC is an ArrayList, with known properties 

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

मैं केवल यूनिट परीक्षणों में प्रतिबिंबित प्रतिलिपि या तत्काल धारावाहिक/deserializing जैसे अन्य दृष्टिकोणों का उपयोग करता हूं। मेरे लिए, वे मुख्य रूप से प्रदर्शन चिंताओं के कारण, उत्पादन कोड के लिए कम उपयुक्त महसूस करते हैं।

2

जावा (उथले या गहरे) में ऑब्जेक्ट की प्रतिलिपि बनाने के कई तरीके हैं।
यह Answer आपकी मदद करेगा।

2

आप ऑर्गेन क्लोनिंग के लिए org.apache.commons.lang3.SerializationUtils क्लास का उपयोग कर सकते हैं, - कक्षा को Serializable इंटरफ़ेस को कार्यान्वित करना चाहिए।

  • className copyobject = SerializationUtils.clone (classobjectTocopy)

SerializationUtils.clone भी Google अनुप्रयोग इंजन उदाहरण