আমি জাভাতে কোনও কীভাবে অনুলিপি করব?


794

নীচের কোডটি বিবেচনা করুন:

DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'

DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'

dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'

সুতরাং, আমি এটিকে অনুলিপি করে অনুলিপি dumকরতে dumtwoএবং পরিবর্তন dumকরতে চাই dumtwo। কিন্তু উপরের কোডটি তা করছে না। আমি যখন কিছু পরিবর্তন করি তখন dumএকই পরিবর্তনও ঘটে চলেছে dumtwo

আমার ধারণা, যখন আমি বলি dumtwo = dum, জাভা কেবলমাত্র রেফারেন্সটি অনুলিপি করে । সুতরাং, এর একটি নতুন প্রতিলিপি তৈরি dumএবং এটি নির্ধারণ করার কোনও উপায় আছে dumtwoকি?

উত্তর:


611

একটি অনুলিপি নির্মাণকারী তৈরি করুন:

class DummyBean {
  private String dummy;

  public DummyBean(DummyBean another) {
    this.dummy = another.dummy; // you can access  
  }
}

প্রতিটি বস্তুর একটি ক্লোন পদ্ধতিও রয়েছে যা বস্তুটি অনুলিপি করতে ব্যবহার করা যেতে পারে, তবে এটি ব্যবহার করবেন না। ক্লাস তৈরি করা এবং অনুপযুক্ত ক্লোন পদ্ধতিটি করা খুব সহজ। আপনি যদি এটি করতে যাচ্ছেন তবে কার্যকর জাভাতে জোশুয়া ব্লচ সম্পর্কে এটি যা বলেছে তা অন্ততপক্ষে পড়ুন ।


45
তবে তারপরে তার কোডটি ডামিবিয়ান টুতে পরিবর্তন করতে হবে = নতুন ডামিবিয়ান (এক); রাইট?
ক্রিস কে

12
এই পদ্ধতিটি কি গভীর অনুলিপি হিসাবে কার্যকরভাবে কার্যকরভাবে সম্পাদন করে?
ম্যাথু পিজিয়াক

124
@ ম্যাথেজপিজিয়াক, আমার কাছে - এটি কোনও গভীর ক্লোন হবে না যেহেতু কোনও নেস্টেড অবজেক্টগুলি এখনও মূল উত্স উদাহরণটি উল্লেখ করবে, প্রতিলিপি (অ-মান টাইপ) অবজেক্টটি উপরের মতো একই কনস্ট্রাক্টর টেম্পলেট সরবরাহ না করা পর্যন্ত একটি সদৃশ নয়।
স্লিভারনিঞ্জা - এমএসএফটি

17
@ টিম্ম্ম্ম: হ্যাঁ, তারা একই স্ট্রিংটিকে রেফারেন্স করবে তবে এটি পরিবর্তনযোগ্য, এটি ঠিক আছে। আদিমদের জন্য একই। অ-আদিমদের জন্য, আপনি কেবল অনুলিপি কন্ট্রাক্টর কল করবেন। উদাহরণস্বরূপ, যদি ডমিবিয়ান ফুবারকে রেফারেন্স করে তবে ফুবারের কনট্রাক্টর FooBar (অন্য কোনও FooBar) থাকা উচিত, এবং ডামিকে এ বলা উচিত = fooبار = new FooBar (another.foobar)
উদাহরণস্বরূপ

7
@ ক্রিশ্চিয়ানভিয়েলমা: না, এটি "জোহানো" হবে না। টিএমএমএম যেমন বলেছিল, স্ট্রিংটি নিজেই অপরিবর্তনীয়। একটি দিয়ে, সেটডমি (..) দিয়ে আপনি "জোহান্দো" তে নির্দেশ করতে একটিতে রেফারেন্স সেট করেছেন, তবে একটিতে নয়।
কেউলেজে

404

বেসিক: জাভাতে অবজেক্ট অনুলিপি করা।

আমাদের একটি object- জেনে নিই obj1, যে দুটি বস্তুর রয়েছে containedObj1 এবং containedObj2
এখানে চিত্র বর্ণনা লিখুন

অগভীর অনুলিপি:
অগভীর অনুলিপি instanceএকই শ্রেণীর একটি নতুন তৈরি করে এবং সমস্ত ক্ষেত্রটি নতুন দৃষ্টান্তে অনুলিপি করে তা ফেরত দেয়। অবজেক্ট ক্লাস একটি cloneপদ্ধতি সরবরাহ করে এবং অগভীর অনুলিপি করার জন্য সহায়তা সরবরাহ করে।
এখানে চিত্র বর্ণনা লিখুন

গভীর অনুলিপি:
একটি গভীর অনুলিপি ঘটে যখন কোনও বস্তু যার সাথে সম্পর্কিত হয় তার সাথে অনুলিপি করা হয় । নীচে obj1একটি গভীর অনুলিপি সম্পাদনা করার পরে চিত্রের নীচে প্রদর্শিত হবে। কেবল obj1অনুলিপি করা হয়নি , তবে এর মধ্যে থাকা অবজেক্টগুলিও অনুলিপি করা হয়েছে। আমরা Java Object Serializationএকটি গভীর অনুলিপি তৈরি করতে ব্যবহার করতে পারি । দুর্ভাগ্যক্রমে, এই পদ্ধতির কিছু সমস্যা রয়েছে ( বিস্তারিত উদাহরণ )।
এখানে চিত্র বর্ণনা লিখুন

সম্ভাব্য সমস্যা:
clone সঠিকভাবে প্রয়োগ করা জটিল।
এটা ব্যবহার করা ভালো ডিফেন্সিভ অনুলিপি , কপি কনস্ট্রাকটর অথবা (@egaga উত্তর হিসাবে) স্ট্যাটিক কারখানা পদ্ধতি

  1. আপনার যদি কোনও অবজেক্ট থাকে, আপনি জানেন যে একটি পাবলিক clone()পদ্ধতি রয়েছে তবে আপনি কম্পাইল করার সময় অবজেক্টের ধরণটি জানেন না, তবে আপনার সমস্যা আছে। জাভা একটি ইন্টারফেস বলা হয় Cloneable। বাস্তবে, যদি আমরা কোনও বস্তু তৈরি করতে চাই তবে আমাদের এই ইন্টারফেসটি বাস্তবায়ন করা উচিত CloneableObject.cloneহয় সংরক্ষিত , তাই আমরা উচিত নয় ওভাররাইড অনুক্রমে একটি সর্বজনীন পদ্ধতি সঙ্গে এটা অ্যাক্সেস করা জন্য।
  2. যখন আমরা একটি জটিল বস্তুর গভীর অনুলিপি করার চেষ্টা করি তখন আর একটি সমস্যা দেখা দেয় । ধরুন যে সমস্ত সদস্য অবজেক্ট ভেরিয়েবলের পদ্ধতিটি গভীর অনুলিপিও করে, এটি অনুমানের পক্ষে খুব ঝুঁকিপূর্ণ। আপনার অবশ্যই সমস্ত ক্লাসের কোডটি নিয়ন্ত্রণ করতে হবে।clone()

উদাহরণস্বরূপ org.apache.commons.lang.SerializationUtils এর সিরিয়ালাইজেশন ( উত্স ) ব্যবহার করে ডিপ ক্লোন করার পদ্ধতি থাকবে । যদি আমাদের শিমটি ক্লোন করা প্রয়োজন তবে org.apache.commons.beanutils ( উত্স ) এ কয়েকটি ইউটিলিটি পদ্ধতি রয়েছে ।

  • cloneBean এমনকি সিম শ্রেণি নিজেই ক্লোনেবেল বাস্তবায়ন না করে, উপলভ্য সম্পত্তি গেটার এবং সেটটারদের উপর ভিত্তি করে একটি শিম ক্লোন করবে।
  • copyProperties সমস্ত ক্ষেত্রে যেখানে সম্পত্তির নাম একই হয় তার জন্য মূল শিম থেকে গন্তব্য শিমের জন্য সম্পত্তি মানগুলি অনুলিপি করবে।

1
আপনি দয়া করে ব্যাখ্যা করতে পারেন যে অন্যটির মধ্যে কী রয়েছে?
ফ্রাক্যুয়েজার

1
@ চন্দ্র শেখর "অগভীর অনুলিপি একই বর্গের একটি নতুন উদাহরণ তৈরি করে এবং সমস্ত ক্ষেত্রকে নতুন দৃষ্টান্তে অনুলিপি করে ফেরত দেয়" সমস্ত ক্ষেত্রের উল্লেখ করা ভুল, বিসিজেড অবজেক্টগুলি কেবল রেফারেন্সগুলি অনুলিপি করে না যা কোন পয়েন্টকে নির্দেশ করে পুরানো এক (মূল) একই জিনিসটি নির্দেশ করছিল।
জাভা

4
@ সানি - চন্দ্রের বর্ণনাটি সঠিক। এবং আপনার ঘটনার বিবরণও তাই; আমি বলছি যে আপনার কাছে "সমস্ত ক্ষেত্রের অনুলিপি" অর্থটির একটি ভুল ধারণা রয়েছে। ক্ষেত্রটি হল রেফারেন্স, এটি অবজেক্টটি উল্লেখ করা হচ্ছে না। "সমস্ত ক্ষেত্র অনুলিপি করা" এর অর্থ "সেই সমস্ত উল্লেখগুলি অনুলিপি করা"। এটি ভাল যে আপনি ঠিক তার অর্থ কি তা নির্দেশ করেছেন, অন্য যে কারও কাছে আপনার মত একই ভুল ব্যাখ্যা রয়েছে, "সমস্ত ক্ষেত্রের অনুলিপি" বয়ানটির। :)
নির্মাতা স্টিভ

2
... যদি আমরা কিছু নিম্ন-স্তরের ওও ভাষার শর্তাবলী বিবেচনা করি তবে অবজেক্টগুলিতে "পয়েন্টার" দিয়ে এমন ক্ষেত্রটিতে মেমরির ঠিকানা থাকবে (যেমন "0x70FF1234") যেখানে অবজেক্টের ডেটা পাওয়া যায়। সেই ঠিকানাটি হ'ল "ক্ষেত্রের মান" যা অনুলিপি করা হচ্ছে (নির্ধারিত)। আপনি ঠিক বলেছেন যে শেষ ফলাফলটি হ'ল উভয় বস্তুর ক্ষেত্রে এমন ক্ষেত্র রয়েছে যা একই বস্তুকে (পয়েন্ট এ) উল্লেখ করে।
টুলমেকারস্টেভ

127

প্যাকেজে import org.apache.commons.lang.SerializationUtils;একটি পদ্ধতি রয়েছে:

SerializationUtils.clone(Object);

উদাহরণ:

this.myObjectCloned = SerializationUtils.clone(this.object);

59
যতক্ষণ না অবজেক্টটি প্রয়োগ করেSerializable
অ্যান্ড্রয়েডারসন

2
এই ক্ষেত্রে ক্লোন করা বস্তুর মূলটির কোনও রেফারেন্স নেই, যদি শেষটি স্থির হয়।
দান্তে

8
তৃতীয় পক্ষের গ্রন্থাগারটি কেবল ক্লোন অবজেক্ট!
খান

2
@ খান, "কেবলমাত্র একটি তৃতীয় পক্ষের লাইব্রেরি" সম্পূর্ণ আলাদা আলোচনা! : ডি
চার্লস উড

103

ঠিক নীচের মত অনুসরণ করুন:

public class Deletable implements Cloneable{

    private String str;
    public Deletable(){
    }
    public void setStr(String str){
        this.str = str;
    }
    public void display(){
        System.out.println("The String is "+str);
    }
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

এবং যেখানেই আপনি অন্য কোনও অবজেক্ট পেতে চান, সহজ ক্লোনিং করুন। উদাহরণ:

Deletable del = new Deletable();
Deletable delTemp = (Deletable ) del.clone(); // this line will return you an independent
                                 // object, the changes made to this object will
                                 // not be reflected to other object

1
আপনি এটি পরীক্ষা করেছেন? আমি এটি আমার প্রকল্পের জন্য ব্যবহার করতে পারি এবং এটি সঠিক হওয়া গুরুত্বপূর্ণ।
ধোঁয়াশা

2
@ মিস্টি আমি এটি পরীক্ষা করেছি। আমার প্রযোজনা অ্যাপ্লিকেশনটিতে পুরোপুরি কাজ করে
আন্দ্রেই কোভালচুক

ক্লোনিংয়ের পরে, আপনি যখন আসল অবজেক্টটি সংশোধন করবেন তখন এটি ক্লোনটিকেও সংশোধন করবে।
সিবিশ

4
যে এটা এই ভুল না একটি গভীর কপি, যার জন্য অনুরোধ করা হয়েছে।
ব্লুহর্ন

1
এই পদ্ধতিতে পয়েন্টারটি ক্লোনযোগ্য বস্তুর জন্য নির্দেশ করে তবে উভয় বস্তুর অভ্যন্তরের সমস্ত বৈশিষ্ট্য সমান, সুতরাং মেমরিতে একটি নতুন অবজেক্ট তৈরি হয়েছে, তবে প্রতিটি বস্তুর অভ্যন্তরের ডেটা মেমরি থেকে একই ডেটা
ওমর হোসামএলডিন

40

রিফ্লেকশন এপিআই ব্যবহার করার জন্য কেন কোনও উত্তর নেই?

private static Object cloneObject(Object obj){
        try{
            Object clone = obj.getClass().newInstance();
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                field.set(clone, field.get(obj));
            }
            return clone;
        }catch(Exception e){
            return null;
        }
    }

এটা সত্যিই সহজ।

সম্পাদনা: পুনরাবৃত্তি মাধ্যমে শিশু অবজেক্ট অন্তর্ভুক্ত

private static Object cloneObject(Object obj){
        try{
            Object clone = obj.getClass().newInstance();
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                if(field.get(obj) == null || Modifier.isFinal(field.getModifiers())){
                    continue;
                }
                if(field.getType().isPrimitive() || field.getType().equals(String.class)
                        || field.getType().getSuperclass().equals(Number.class)
                        || field.getType().equals(Boolean.class)){
                    field.set(clone, field.get(obj));
                }else{
                    Object childObj = field.get(obj);
                    if(childObj == obj){
                        field.set(clone, clone);
                    }else{
                        field.set(clone, cloneObject(field.get(obj)));
                    }
                }
            }
            return clone;
        }catch(Exception e){
            return null;
        }
    }

এটি দেখতে আরও ভাল দেখায়, তবে আপনাকে কেবল চূড়ান্ত ক্ষেত্রগুলি বিবেচনা করতে হবে কারণ সেটএ্যাক্সেসিবল (সত্য) ব্যর্থ হতে পারে, তাই আপনাকে ফিল্ড.সেট (ক্লোন, ফিল্ড.জেট (আপত্তি)) আলাদাভাবে কল করার সময় নিক্ষিপ্ত ব্যতিক্রম আইল্যাগালএ্যাক্সেসেপশন হ্যান্ডেল করতে হবে।
সর্বাধিক

1
আমি এটিকে খুব পছন্দ করেছিলাম তবে আপনি জেনেরিকগুলি ব্যবহার করার জন্য এটি কী চুল্লি করতে পারেন? প্রাইভেট স্ট্যাটিক <টি> টি ক্লোনঅবজেক্ট (টি আপত্তি) {....}
অ্যাডেলিন

2
আমি মনে করি এটির সমস্যাটি যখন আমাদের কাছে সম্পত্তি থেকে এর পিতামাতার কাছে রেফারেন্স থাকে: Class A { B child; } Class B{ A parent; }
ntthai

এমনকি এই পরিস্থিতিতে এটি ব্যর্থ হয়, পরিচালনা করা দরকার, আমি এটির সাথে খেলব। class car { car car = new car(); }
জান সাবান

2
এটি ত্রুটিযুক্ত প্রবণ। এটি কীভাবে সংগ্রহগুলি পরিচালনা করবে তা নিশ্চিত নয়
এসিভি

31

আমি এটির ক্রমিকায়নের জন্য গুগলের জেএসএন লাইব্রেরি ব্যবহার করি তারপরে সিরিয়ালাইজড অবজেক্টটির একটি নতুন উদাহরণ তৈরি করুন। এটি কয়েকটি সীমাবদ্ধতার সাথে গভীর অনুলিপি করে:

  • কোনও পুনরাবৃত্ত তথ্যসূত্র থাকতে পারে না

  • এটি পৃথক প্রকারের অ্যারেগুলি অনুলিপি করবে না

  • অ্যারে এবং তালিকা টাইপ করা উচিত বা এটি ইনস্ট্যান্ট করার জন্য শ্রেণিটি খুঁজে পাবে না to

  • আপনি নিজেকে যে ক্লাসে ঘোষণা করেছেন তাতে আপনার স্ট্রিংগুলি আবশ্যক হতে পারে

আমি এই ক্লাসটি ব্যবহারকারীর পছন্দগুলি, উইন্ডোজ এবং রানটাইমগুলিতে পুনরায় লোড করার দরকার নেই তা সংরক্ষণ করতে ব্যবহার করি। এটি ব্যবহার করা খুব সহজ এবং কার্যকর।

import com.google.gson.*;

public class SerialUtils {

//___________________________________________________________________________________

public static String serializeObject(Object o) {
    Gson gson = new Gson();
    String serializedObject = gson.toJson(o);
    return serializedObject;
}
//___________________________________________________________________________________

public static Object unserializeObject(String s, Object o){
    Gson gson = new Gson();
    Object object = gson.fromJson(s, o.getClass());
    return object;
}
       //___________________________________________________________________________________
public static Object cloneObject(Object o){
    String s = serializeObject(o);
    Object object = unserializeObject(s,o);
    return object;
}
}

এটি দুর্দান্ত কাজ করে। আপনি যদি তালিকা <ইনটেইগার> এর মতো কিছু ক্লোন করার চেষ্টা করেন তবে দেখুন। এটি বগি হবে, আমার পূর্ণসংখ্যাগুলি ডাবলস, 100.0 এ পরিণত হবে। তারা কেন এমন হয় তা বুঝতে আমার অনেক সময় লেগেছে। সমাধানটি ছিল একে একে তাদের পূর্ণসংখ্যার ক্লোন করা এবং একটি চক্রের তালিকায় যুক্ত করা।
পাকজিস

24

হ্যাঁ, আপনি কেবলমাত্র অবজেক্টটির জন্য একটি রেফারেন্স দিচ্ছেন। আপনি বস্তু ক্লোন করতে পারেন যদি এটা প্রয়োগ Cloneable

অনুলিপিযুক্ত বিষয়গুলি সম্পর্কে এই উইকি নিবন্ধটি দেখুন।

এখানে উল্লেখ করুন: অনুলিপি করা অবজেক্ট


14

Cloneableআপনার ক্লাসে কোড যুক্ত করুন এবং নীচে দিন

public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

এটা ব্যবহার কর clonedObject = (YourClass) yourClassObject.clone();


12

হ্যাঁ. আপনার অবজেক্টটি গভীরভাবে অনুলিপি করা উচিত ।


1
যেমনটি, এটি মোটেও অনুলিপি নয়।
মাইকেল ময়র্স

এটি সম্ভবত সবচেয়ে কম সহায়ক উত্তর যা আমি স্ট্যাকওভারফ্লোতে দেখেছি।
সিরিল

12

এটিও কাজ করে। মডেল ধরে

class UserAccount{
   public int id;
   public String name;
}

প্রথমে compile 'com.google.code.gson:gson:2.8.1'আপনার অ্যাপে> গ্রেডেল এবং সিঙ্কে যুক্ত করুন। তারপর

Gson gson = new Gson();
updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);

transientঅ্যাক্সেস মডিফায়ারের পরে কীওয়ার্ড ব্যবহার করে আপনি কোনও ক্ষেত্র ব্যবহার বাদ দিতে পারেন ।

দ্রষ্টব্য: এটি খারাপ অভ্যাস। এছাড়াও ব্যবহার করতে সুপারিশ করি না Cloneableবা JavaSerializationএটা ধীর এবং ভাঙ্গা হচ্ছে। সেরা পারফরম্যান্স রেফের জন্য অনুলিপি নির্মাণকারী লিখুন ।

কিছুটা এইরকম

class UserAccount{
        public int id;
        public String name;
        //empty constructor
        public UserAccount(){}
        //parameterize constructor
        public UserAccount(int id, String name) {
            this.id = id;
            this.name = name;
        }

        //copy constructor
        public UserAccount(UserAccount in){
            this(in.id,in.name);
        }
    }

90000 পুনরাবৃত্তির পরীক্ষার পরিসংখ্যান:
রেখাটি 808msUserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class); লাগে

লাইনটি 1 এমএসেরওUserAccount clone = new UserAccount(aO); কম সময় নেয়

উপসংহার: আপনার বস যদি পাগল হয় এবং আপনি গতি পছন্দ করেন তবে জিএসএন ব্যবহার করুন। আপনি যদি মানের পছন্দ করেন তবে দ্বিতীয় অনুলিপি নির্মাণকারী ব্যবহার করুন।

আপনি অ্যান্ড্রয়েড স্টুডিওতে অনুলিপি নির্মাণকারী কোড জেনারেটর প্লাগইন ব্যবহার করতে পারেন ।


এটি খারাপ অভ্যাস হলে কেন আপনি এটির পরামর্শ দিয়েছেন?
পার্থ মেহরোত্রা

ধন্যবাদ এখন উন্নত @ParthMehrotra
কমর


9

একটি গভীর ক্লোনিং ইউটিলিটি ব্যবহার করুন:

SomeObjectType copy = new Cloner().deepClone(someObject);

এটি যে কোনও জাভা বস্তুটিকে গভীরভাবে অনুলিপি করবে, https://github.com/kostaskougios/cloning এ এটি পরীক্ষা করে দেখুন


1
কাস্টম ক্লাস ব্যবহার করে আমার পক্ষে কাজ করেনি। নিম্নলিখিত ব্যতিক্রম পাচ্ছেন: java.lang.NoClassDefFoundError: sun.reflect.ReFlectionFactory
স্টেফানজুঙ্কার

9

ডিপ ক্লোনিং হ'ল আপনার উত্তর, যার জন্য Cloneableইন্টারফেস প্রয়োগ করা এবং clone()পদ্ধতিটিকে ওভাররাইড করা প্রয়োজন ।

public class DummyBean implements Cloneable {

   private String dummy;

   public void setDummy(String dummy) {
      this.dummy = dummy;
   }

   public String getDummy() {
      return dummy;
   }

   @Override
   public Object clone() throws CloneNotSupportedException {
      DummyBean cloned = (DummyBean)super.clone();
      cloned.setDummy(cloned.getDummy());
      // the above is applicable in case of primitive member types like String 
      // however, in case of non primitive types
      // cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
      return cloned;
   }
}

আপনি এটিকে এভাবে ডাকবেন DummyBean dumtwo = dum.clone();


2
dummy, এ String, পরিবর্তনযোগ্য, আপনার এটি অনুলিপি করার দরকার নেই
স্টিভ কুও

7

এটি করতে আপনাকে কোনওভাবে অবজেক্টটি ক্লোন করতে হবে। যদিও জাভাতে ক্লোনিং মেকানিজম রয়েছে, আপনার যদি এটি না করেন তবে এটি ব্যবহার করবেন না। একটি অনুলিপি পদ্ধতি তৈরি করুন যা অনুলিপি আপনার জন্য কাজ করে এবং তারপরে:

dumtwo = dum.copy();

একটি অনুলিপি সম্পন্ন করার জন্য বিভিন্ন কৌশল সম্পর্কে আরও কিছু পরামর্শ এখানে


6

সুস্পষ্টভাবে অনুলিপি করা ব্যতীত অন্য একটি পদ্ধতি হ'ল অবজেক্টটিকে অপরিবর্তনীয় করে তোলা (কোনও setবা অন্য কোনও মিউটর পদ্ধতি নয়)। এভাবে কখনই প্রশ্ন ওঠে না। অপরিবর্তনীয়তা বৃহত্তর অবজেক্টগুলির সাথে আরও কঠিন হয়ে ওঠে তবে এর অন্য দিকটি হ'ল এটি আপনাকে সুসংগত ছোট ছোট বস্তু এবং সংমিশ্রণে বিভক্ত করার দিকে ধাক্কা দেয়।


5

উদাহরণস্বরূপ অনুলিপি এর অনুলিপি নির্মাণকারী পদ্ধতির বিকল্প method আপনার সম্ভবত ইতিমধ্যে একটি পজো রয়েছে, সুতরাং কেবলমাত্র অন্য একটি পদ্ধতি যুক্ত করুন copy()যা প্রারম্ভিক বস্তুর অনুলিপি দেয়।

class DummyBean {
    private String dummyStr;
    private int dummyInt;

    public DummyBean(String dummyStr, int dummyInt) {
        this.dummyStr = dummyStr;
        this.dummyInt = dummyInt;
    }

    public DummyBean copy() {
        return new DummyBean(dummyStr, dummyInt);
    }

    //... Getters & Setters
}

আপনার যদি ইতিমধ্যে একটি থাকে DummyBeanএবং একটি অনুলিপি চান:

DummyBean bean1 = new DummyBean("peet", 2);
DummyBean bean2 = bean1.copy(); // <-- Create copy of bean1 

System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());

//Change bean1
bean1.setDummyStr("koos");
bean1.setDummyInt(88);

System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());

আউটপুট:

bean1: peet 2
bean2: peet 2

bean1: koos 88
bean2: peet 2

তবে উভয়ই ভাল কাজ করে, এটি শেষ পর্যন্ত আপনার ...



3

আপনি এক্স স্ট্রিমের সাথে http://x-stream.github.io/ থেকে স্বয়ংক্রিয়ভাবে গভীর অনুলিপি করতে পারেন :

এক্সস্ট্রিম হ'ল এক্সএমএল এবং আবার ফিরে জিনিসগুলিকে সিরিয়ালাইজ করার জন্য একটি সাধারণ লাইব্রেরি।

এটি আপনার প্রকল্পে যুক্ত করুন (যদি মাভেন ব্যবহার করছেন)

<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.3.1</version>                
</dependency>

তারপর

DummyBean dum = new DummyBean();
dum.setDummy("foo");
DummyBean dumCopy = (DummyBean) XSTREAM.fromXML(XSTREAM.toXML(dum));

এটির সাথে কোনও ক্লোনিং ইন্টারফেস প্রয়োগ করার প্রয়োজন ছাড়াই আপনার একটি অনুলিপি রয়েছে।


29
এক্সএমএলে / থেকে রূপান্তর করা খুব ... মার্জিত বলে মনে হচ্ছে না। হালকা করে রাখতে!
টিম্ম্ম্ম

java.beans.XMLEncoderএকটি স্ট্যান্ডার্ড জাভা এপিআইয়ের দিকে একবার নজর দিন যা এক্সএমএলকেও সিরিয়ালাইজ করে (যদিও গভীর অনুলিপি উদ্দেশ্যে নয়)।
জাইমে হাবলুটজেল

1
আপনি বুঝতে পারেন যে এটি কতটা ভারী?
মাহিদ্দিন

1
আমার মতে অনেকটা ওভারহেডের উপায়, যেহেতু আপনাকে একটি তৃতীয় পক্ষের লাইব্রেরি যুক্ত করা উচিত এবং অবজেক্ট সিরিয়ালাইজেশন করা উচিত যা সম্ভবত কার্যত বিশাল পারফরম্যান্স প্রভাব ফেলে।
NiThDi

2
public class MyClass implements Cloneable {

private boolean myField= false;
// and other fields or objects

public MyClass (){}

@Override
public MyClass clone() throws CloneNotSupportedException {
   try
   {
       MyClass clonedMyClass = (MyClass)super.clone();
       // if you have custom object, then you need create a new one in here
       return clonedMyClass ;
   } catch (CloneNotSupportedException e) {
       e.printStackTrace();
       return new MyClass();
   }

  }
}

এবং আপনার কোডে:

MyClass myClass = new MyClass();
// do some work with this object
MyClass clonedMyClass = myClass.clone();

2
ঘোষণাপত্রে "ক্লোননটসপোর্টার্ড এক্সেক্সশন নিক্ষেপ" সেট করার কোনও অর্থ নেই, যদি আপনি ব্যতিক্রমটি ধরার চেষ্টা করেন এবং আপ না ফেলে থাকেন তবে। সুতরাং, আপনি এটি সরাতে পারেন।
খ্রিস্টান

2

আপনি যে বস্তুটি অনুলিপি করতে চান সেটি পাস করুন এবং যে জিনিসটি আপনি চান তা পেতে:

private Object copyObject(Object objSource) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(objSource);
            oos.flush();
            oos.close();
            bos.close();
            byte[] byteData = bos.toByteArray();
            ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
            try {
                objDest = new ObjectInputStream(bais).readObject();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return objDest;

    }

এবার objDestকাঙ্ক্ষিত বস্তুটিকে পার্স করুন ।

শুভ কোডিং!


1

আপনি পদ্ধতিটি প্রয়োগ Cloneableএবং ব্যবহার করার চেষ্টা করতে পারেন clone(); যাইহোক, আপনি ক্লোন পদ্ধতি আপনি উচিত ব্যবহার করেন - সর্বদা ওভাররাইড - স্ট্যান্ডার্ড দ্বারা Objectএর public Object clone()পদ্ধতি।


1

আপনি উৎস ফাইলে একটি টীকা যোগ করতে পারেন, তাহলে একটি টীকা প্রসেসর বা মত কোড জেনারেটরের এই এক ব্যবহার করা যাবে।

import net.zerobuilder.BeanBuilder

@BeanBuilder
public class DummyBean { 
  // bean stuff
}

একটি শ্রেণি DummyBeanBuildersউত্পন্ন হবে, যার dummyBeanUpdaterঅগভীর অনুলিপি তৈরি করার জন্য একটি অচল পদ্ধতি রয়েছে , আপনি নিজে নিজে যা করেন তেমনভাবে would

DummyBean bean = new DummyBean();
// Call some setters ...
// Now make a copy
DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done();

0

gsonকোনও বস্তুর সদৃশ করার জন্য ব্যবহার করুন ।

public static <T>T copyObject(Object object){
    Gson gson = new Gson();
    JsonObject jsonObject = gson.toJsonTree(object).getAsJsonObject();
    return gson.fromJson(jsonObject,(Type) object.getClass());
}

ধরুন আমার একটা অবজেক্ট আছে person.সেই

Person copyPerson = copyObject(person);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.