java - জাভা প্রোগ্রামিং




আমি কিভাবে জাভা একটি বস্তুর অনুলিপি করব? (14)

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

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

এই clonedObject = (YourClass) yourClassObject.clone();

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

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'

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

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


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


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

import net.zerobuilder.BeanBuilder

@BeanBuilder
public class DummyBean { 
  // bean stuff
}

DummyBeanBuilders একটি শ্রেণির DummyBeanBuilders হবে, যা একটি স্ট্যাটিক পদ্ধতি dummyBeanUpdater অগভীর কপি তৈরি করতে পারে, একইভাবে আপনি নিজে নিজে এটি করবেন।

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

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

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 পার্স।

শুভ কোডিং!


এই খুব কাজ করে। মডেল assuming

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 পুনরাবৃত্তি পরীক্ষার পরিসংখ্যান:
লাইন UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class); 808ms লাগে

লাইন UserAccount clone = new UserAccount(aO); 1ms কম লাগে

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

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


একটি কপি গঠনকারী তৈরি করুন:

class DummyBean {
  private String dummy;

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

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



কেন প্রতিফলন API ব্যবহার করার জন্য কোন উত্তর নেই?

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;
        }
    }

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

SerializationUtils.clone(Object);

উদাহরণ:

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

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

dumtwo = dum.copy();

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


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


হ্যাঁ, আপনি শুধু বস্তুর একটি রেফারেন্স করছেন। Cloneable প্রয়োগ করলে আপনি বস্তুটি ক্লোন করতে পারেন।

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

এখানে পড়ুন: বস্তু কপি করা


মৌলিক: জাভা বস্তু কপি করা।

আসুন আমরা একটি বস্তু অনুমান করি - obj1 , যা দুটি বস্তু ধারণ করে, এতে রয়েছে obj1 এবং অন্তর্ভুক্ত obj1

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

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

সম্ভাব্য সমস্যা:
clone সঠিকভাবে বাস্তবায়ন চতুর।
প্রতিরক্ষামূলক অনুলিপি , কপি কন্সট্রকটারগুলি (@egaga উত্তর হিসাবে) বা স্ট্যাটিক ফ্যাক্টরি পদ্ধতিগুলি ব্যবহার করা ভাল

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

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

  • ক্লোন cloneBean উপলব্ধ সম্পত্তি উত্তোলনকারী এবং setters উপর ভিত্তি করে একটি মটরশুটি ক্লোন করবে, এমনকি শিম বর্গ নিজেই Cloneable বাস্তবায়ন না করেও।
  • কপির প্রোপার্টিগুলি সমস্ত ক্ষেত্রেই মূল copyProperties থেকে গন্তব্য শিমের সম্পত্তি মান কপি করবে যেখানে সম্পত্তিগুলির নাম একই।

class DB {
  private String dummy;

  public DB(DB one) {
    this.dummy = one.dummy; 
  }
}




clone