2013-03-21 7 views
21

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

मैंने कल क्लोनेबल लागू किया और फिर मुझे एहसास हुआ कि मुझे गैर स्ट्रिंग/प्राइमेटिव तत्वों के लिए अपना स्वयं का संशोधन प्रदान करना पड़ा। तब मुझे BeanUtils.copyProperties के बारे में सूचित किया गया था जिसका मैं अब उपयोग कर रहा हूं। दोनों कार्यान्वयन एक समान कार्यक्षमता प्रदान करने लगते हैं।

धन्यवाद

+0

तो आप वास्तव में क्या सवाल पूछ रहे हैं? –

+1

क्या हमें क्लोन या बीनयूल्ट्स.copyProperties का उपयोग करना चाहिए और क्यों – Biscuit128

उत्तर

19

जोश ब्लोच कुछ उचित तर्क प्रदान करता है (जिसमें आपने प्रदान किया है) जिसमें Cloneable मूल रूप से त्रुटिपूर्ण है, इसके बजाय एक प्रतिलिपि बनाने वाला पक्ष है। here देखें।

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

BeanUtils.copyProperties अक्सर आपकी कक्षाओं को समर्थित करने के बिना प्रतिलिपि बनाने का एक कम घुसपैठ तरीका होता है, और यह कंपोजिटिंग ऑब्जेक्ट्स में कुछ अद्वितीय लचीलापन प्रदान करता है।

ने कहा, copyProperties हमेशा एक-आकार-फिट नहीं है। आप किसी बिंदु पर विशिष्ट रचनाकारों वाले प्रकारों वाले ऑब्जेक्ट्स का समर्थन करने की आवश्यकता हो सकती है, लेकिन अभी भी उत्परिवर्तनीय हैं। आपकी ऑब्जेक्ट्स उन अपवादों के आसपास काम करने के लिए आंतरिक विधियों या रचनाकारों का समर्थन कर सकती हैं, या आप प्रतिलिपि बनाने के लिए विशिष्ट प्रकारों को कुछ बाहरी टूल में पंजीकृत कर सकते हैं, लेकिन यह कुछ स्थानों तक नहीं पहुंच सकता है जो clone() भी कर सकते हैं। यह अच्छा है, लेकिन अभी भी सीमाएं हैं।

+0

'जोश ब्लोच के प्रभावी जावा' नोट्स के रूप में अच्छा जवाब। क्या मैं संक्षेप में बता सकता हूं कि "दोनों का उपयोग सेनियस के आधार पर किया जा सकता है"? लेकिन दोनों की सीमाएं हैं। –

0

क्लोन वस्तु की एक उथले कॉपी बन जाती है, क्लोन वस्तु हमेशा मूल एक के रूप में एक ही कक्षा की है। सभी फ़ील्ड, निजी या कॉपी नहीं हैं।

BeanUtils.copyProperties API सभी मामलों के लिए मूल बीन से गंतव्य बीन से संपत्ति मूल्यों की प्रतिलिपि करें जहां संपत्ति के नाम समान हैं।

मेरे लिए, इन दो अवधारणाओं में बहुत कम आम है।

+3

हाय। मैं सिर्फ डेविल वकील खेलना आपके फैसले पर सवाल नहीं उठा रहा हूं। एक ही प्रकार के ऑब्जेक्ट को उसी डेटा के साथ बनाने के लिए क्लोन का उद्देश्य नहीं है? यदि आप एक खाली वस्तु (एक खाली कैनवास) बनाने और गुणों की प्रतिलिपि बनाने का उपयोग करते हैं - क्या हम अनिवार्य रूप से वही काम नहीं कर रहे हैं? – Biscuit128

1

आपके प्रश्न से मुझे लगता है कि आपको गहरी प्रति ऑब्जेक्ट की आवश्यकता है। यदि यह मामला clone विधि का उपयोग नहीं करता है क्योंकि यह पहले से ही oracle docs में निर्दिष्ट है कि यह संबंधित ऑब्जेक्ट के उथले प्रति प्रदान करता है। और मेरे पास BeanUtils.copyProperties एपीआई के बारे में पर्याप्त जानकारी नहीं है।
नीचे दिया गया deep copy का छोटा डेमो है। यहां मैं primitive array की गहरी प्रतिलिपि बना रहा हूं। आप इस कोड को किसी भी प्रकार की ऑब्जेक्ट से आजमा सकते हैं।

import java.io.*; 
class ArrayDeepCopy 
{ 
    ByteArrayOutputStream baos; 
    ByteArrayInputStream bins; 
    public void saveState(Object obj)throws Exception //saving the stream of bytes of object to `ObjectOutputStream`. 
    { 
     baos = new ByteArrayOutputStream(); 
     ObjectOutputStream oos = new ObjectOutputStream(baos); 
     oos.writeObject(obj); 
     oos.close(); 
    } 
    public int[][] readState()throws Exception //reading the state back to object using `ObjectInputStream` 
    { 
     bins = new ByteArrayInputStream(baos.toByteArray()); 
     ObjectInputStream oins = new ObjectInputStream(bins); 
     Object obj = oins.readObject(); 
     oins.close(); 
     return (int[][])obj; 
    } 
    public static void main(String[] args) throws Exception 
    { 
     int arr[][]= { 
         {1,2,3}, 
         {4,5,7} 
        }; 
     ArrayDeepCopy ars = new ArrayDeepCopy(); 
     System.out.println("Saving state..."); 
     ars.saveState(arr); 
     System.out.println("State saved.."); 
     System.out.println("Retrieving state.."); 
     int j[][] = ars.readState(); 
     System.out.println("State retrieved..And the retrieved array is:"); 
     for (int i =0 ; i < j.length ; i++) 
     { 
      for (int k = 0 ; k < j[i].length ; k++) 
      { 
       System.out.print(j[i][k]+"\t"); 
      } 
      System.out.print("\n"); 
     } 

    } 
} 
4

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

उदाहरण के लिए मान लीजिए कि आपके पास एक बीन ए है जिसमें फ़ील्ड स्ट्रिंग दिनांक और एक बीन बी है जिसमें एक ही फ़ील्ड java.util.Date date है। BeanUtils के साथ आप स्ट्रिंग मान की प्रतिलिपि बना सकते हैं और डेटफॉर्मैट का उपयोग कर इसे स्वचालित रूप से आज में परिवर्तित कर सकते हैं।

मैंने एसओएपी ऑब्जेक्ट को हाइबरनेट ऑब्जेक्ट्स में कनवर्ट करने के लिए उपयोग किया है, जिसमें समान डेटा प्रकार नहीं हैं।

+1

अब वसंत 4.x के बाद यह प्राचीन प्रकार के सॉस और गंतव्य सेम की तुलना करता है। इसलिए BeanUtils प्रतिलिपि गुणों का उपयोग करते समय सावधान रहें। ध्यान रखें कि आपके पास एक समान आदिम प्रकार हैं जिन्हें स्रोत से गंतव्य तक असाइन किया जा सकता है –

0

क्लोनिंग आपके द्वारा किया जाता है। यदि आप जिस क्लोन को क्लोन करने का प्रयास कर रहे हैं, उसमें एक अन्य उदाहरण का संदर्भ है, तो आपको उस पर क्लोनिंग कोड भी लिखना होगा। क्या होगा यदि उदाहरणों में अन्य मामलों के संदर्भों की श्रृंखला शामिल है? तो यदि आप स्वयं से क्लोनिंग करते हैं, तो संभावना है कि आपको एक छोटी सी जानकारी याद आती है।

अन्यथा पर BeanUtils.copyProperties स्वयं सबकुछ का ख्याल रखता है। यह आपके प्रयास को कम करता है।

2

मुझे लगता है कि आप एक गहरी प्रतिलिपि की तलाश में हैं। आप एक निम्न वर्ग में उपयोग विधि में हो सकते हैं और इसे किसी भी प्रकार के objct के लिए उपयोग कर सकते हैं।

public static <T extends Serializable> T copy(T input) { 
    ByteArrayOutputStream baos = null; 
    ObjectOutputStream oos = null; 
    ByteArrayInputStream bis = null; 
    ObjectInputStream ois = null; 
    try { 
     baos = new ByteArrayOutputStream(); 
     oos = new ObjectOutputStream(baos); 
     oos.writeObject(input); 
     oos.flush(); 

     byte[] bytes = baos.toByteArray(); 
     bis = new ByteArrayInputStream(bytes); 
     ois = new ObjectInputStream(bis); 
     Object result = ois.readObject(); 
     return (T) result; 
    } catch (IOException e) { 
     throw new IllegalArgumentException("Object can't be copied", e); 
    } catch (ClassNotFoundException e) { 
     throw new IllegalArgumentException("Unable to reconstruct serialized object due to invalid class definition", e); 
    } finally { 
     closeQuietly(oos); 
     closeQuietly(baos); 
     closeQuietly(bis); 
     closeQuietly(ois); 
    } 
} 
संबंधित मुद्दे