জাভা: গভীর ক্লোনিং / অনুলিপি করার জন্য একটি উদাহরণ প্রস্তাবিত সমাধান


176

আমি ভাবছি জাভাতে গভীর ক্লোন / উদাহরণের অনুলিপি করার কোনও প্রস্তাবিত উপায় আছে কিনা।

আমার মনে 3 টি সমাধান রয়েছে তবে আমি কিছুটি মিস করতে পারি এবং আমি আপনার মতামত জানাতে চাই

সম্পাদনা করুন: বোহজো প্রস্তাবনা এবং শোধক প্রশ্ন অন্তর্ভুক্ত করুন: এটি অগভীর ক্লোনিংয়ের চেয়ে গভীর ক্লোনিং সম্পর্কে আরও বেশি more

নিজে করো:

বৈশিষ্ট্যগুলির পরে হাতের বৈশিষ্ট্য অনুসারে ক্লোনটি কোড করুন এবং পরীক্ষা করুন যে পরিবর্তনীয় উদাহরণগুলিও ক্লোন হয়ে গেছে।
প্রো:
- কী সম্পাদন করা হবে তার নিয়ন্ত্রণ
- দ্রুত সম্পাদন
কনস:
- লিখতে এবং বজায় রাখতে ক্লান্তি
- বাগ প্রবণ (অনুলিপি / পেস্ট ব্যর্থতা, নিখরচায় সম্পত্তি, পুনরায় স্বাক্ষরিত পারস্পরিক সম্পত্তি)

প্রতিবিম্ব ব্যবহার:

আপনার নিজস্ব প্রতিবিম্ব সরঞ্জাম এবং একটি বাহ্যিক সহায়ক (যেমন জাকার্তা প্রচলিত মটরশুটি) এর সাথে জেনেরিক অনুলিপি পদ্ধতি লেখা সহজ যা একটি লাইনে কাজ করবে।
প্রো:
- লিখতে সহজ
- কোনও রক্ষণাবেক্ষণ
কনস:
- যা ঘটে তার কম নিয়ন্ত্রণ
- প্রতিফলন সরঞ্জামটি সাব অবজেক্টগুলিকে ক্লোন না করলে - পরিবর্তনীয় বস্তুর সাথে বাগ প্রবণ
- ধীর সম্পাদন

ক্লোন কাঠামো ব্যবহার করুন:

এটি আপনার জন্য একটি ফ্রেমওয়ার্ক ব্যবহার করুন, যেমন:
কমন্স-ল্যাং সিরিয়ালাইজেশন
জাভা ডিপ ক্লোনিং লাইব্রেরি
ডজার
ক্রিও

প্রো:
- প্রতিচ্ছবি হিসাবে একই
- ঠিক কি ক্লোন করা হবে তার উপর আরও নিয়ন্ত্রণ।
কনস:
- প্রতিটি পরিবর্তনীয় উদাহরণ পুরোপুরি ক্লোন করা হয় এমনকি শ্রেণিবিন্যাসের শেষেও
- কার্যকর করতে খুব ধীর হতে পারে

রানটাইমে ক্লোন লেখার জন্য বাইটকোড উপকরণ ব্যবহার করুন

জাভাসিট , বিসিইএল বা সিজিবিব সম্ভবত একটি হাত যতটা লিখিত তত দ্রুত ডেডিকেটেড ক্লোনার তৈরি করতে ব্যবহৃত হতে পারে। কেউ এই উদ্দেশ্যে এই সরঞ্জামগুলির একটির ব্যবহার করে একটি লিবিব জানেন?

আমি এখানে কি মিস করেছি?
তুমি কোনটি সুপারিশ কর ?

ধন্যবাদ।


1
দৃশ্যত জাভা ডিপ ক্লোনিং লাইব্রেরি এখানে স্থানান্তরিত হয়েছে: কোড.google.com/p/cloning
Mr_and_Mrs_D

উত্তর:


155

গভীর ক্লোনিংয়ের জন্য (পুরো বস্তুর শ্রেণিবিন্যাসকে ক্লোন করে):

  • commons-lang সিরিয়ালাইজেশন ইউটিস - সিরিয়ালাইজেশন ব্যবহার করে - যদি সমস্ত শ্রেণি আপনার নিয়ন্ত্রণে থাকে এবং আপনি প্রয়োগ করতে বাধ্য করতে পারেন Serializable

  • জাভা ডিপ ক্লোনিং লাইব্রেরি - প্রতিচ্ছবি ব্যবহার করে - আপনি ক্লোন করতে চান এমন ক্লাসগুলি বা অবজেক্টগুলি আপনার নিয়ন্ত্রণের বাইরে চলে গেছে (একটি তৃতীয় পক্ষের গ্রন্থাগার) এবং আপনি সেগুলি বাস্তবায়ন করতে পারবেন না Serializable, বা ক্ষেত্রে আপনি প্রয়োগ করতে চান না Serializable

অগভীর ক্লোনিংয়ের জন্য (শুধুমাত্র প্রথম স্তরের বৈশিষ্ট্যগুলি ক্লোন করে):

আমি ইচ্ছাকৃতভাবে "নিজেই কর" বিকল্পটি বাদ দিয়েছি - এপিআই-র উপরেরটি কী ক্লোন করবেন এবং কী করবেন না (যেমন উদাহরণস্বরূপ ব্যবহার করা transient, বা String[] ignoreProperties) এর উপর একটি ভাল নিয়ন্ত্রণ সরবরাহ করে , সুতরাং চাকাটি পুনর্বহালনের পক্ষে অগ্রাধিকার দেওয়া হয় না।


ধন্যবাদ বোঝো, এটি মূল্যবান। এবং আমি DIY বিকল্প সম্পর্কে আপনার সাথে একমত! আপনি কি কখনও কমন্স সিরিয়ালাইজেশন এবং / অথবা গভীর ক্লোনিং লিব চেষ্টা করেছেন? পারফস কি?
গিলাইম

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

আরে, যদি আমার সত্ত্বা সংযুক্ত থাকে এবং আমার কাছে আলস্য জিনিস থাকে তবে সিরিয়ালাইজেশন ইউটিসগুলি কী অলস বৈশিষ্ট্যের জন্য ডাটাবেসটি পরীক্ষা করে? কিউজ এটি আমি চাই, এবং এটি না!
কসমিন কসমিন

যদি আপনার একটি সক্রিয় সেশন থাকে - হ্যাঁ, এটি হয় does
বোঝো

@ বোঝো সুতরাং আপনার অর্থ কি যদি শিমের মধ্যে থাকা সমস্ত বস্তু ক্রমিকায়িতযোগ্য প্রয়োগ করে, org.apache.commons.beanutils.BeanUtils.cloneBean (আপত্তি) একটি গভীর অনুলিপি করবে?
হপ

36

জোশুয়া ব্লচের বইটিতে "আইটেম 10: ওভাররাইড ক্লোন জাজিলিয়ালি" শিরোনামে একটি সম্পূর্ণ অধ্যায় রয়েছে যেখানে তিনি বেশিরভাগ অংশের জন্য ওভাররাইডিং ক্লোনটিকে একটি খারাপ ধারণা বলে মনে করেন কারণ এটি জাভা স্পেসটি অনেক সমস্যা তৈরি করে।

তিনি কয়েকটি বিকল্প সরবরাহ করেন:

  • কনস্ট্রাক্টরের জায়গায় কারখানার প্যাটার্ন ব্যবহার করুন:

         public static Yum newInstance(Yum yum);
  • একটি অনুলিপি নির্মাণকারী ব্যবহার করুন:

         public Yum(Yum yum);

জাভার সমস্ত সংগ্রহের ক্লাসই অনুলিপি নির্মাণকারীকে সমর্থন করে (উদাঃ নতুন অ্যারেলিস্ট (l);)


1
একমত। আমার প্রকল্পে আমি একটি Copyableইন্টারফেস সংজ্ঞায়িত করেছি যাতে একটি getCopy()পদ্ধতি রয়েছে । কেবল ম্যানুয়ালি প্রোটোটাইপ প্যাটার্ন ব্যবহার করুন।
জিপামপাড়া

ঠিক আছে আমি ক্লোনযোগ্য ইন্টারফেস সম্পর্কে জিজ্ঞাসা করছিলাম না, তবে কীভাবে গভীর ক্লোন / অনুলিপি অপারেশন করা যায়। কোনও কনস্ট্রাক্টর বা কারখানার সাহায্যে আপনাকে এখনও আপনার উত্স থেকে আপনার নতুন উদাহরণ তৈরি করতে হবে।
গিলিয়াম

@ গুইলাউম আমি মনে করি ডিপ ক্লোন / কপি শব্দটি ব্যবহার করার ক্ষেত্রে আপনাকে সতর্কতা অবলম্বন করা উচিত। জাভাতে ক্লোন এবং অনুলিপি একই জিনিস বোঝায় না। জাভা স্পেস এ সম্পর্কে আরও বলার আছে .... আমি মনে করি আমি যা বলতে পারি তার থেকে আপনি একটি গভীর অনুলিপি চান।
লেউউডি

ঠিক আছে জাভা স্পেসটি সম্পর্কে ক্লোনটি কী তা সম্পর্কে সঠিক ... তবে আমরা ক্লোনটির আরও সাধারণ অর্থে কথা বলতে পারি ... উদাহরণস্বরূপ, বোহজোর দ্বারা প্রস্তাবিত একটি লিবের নাম 'জাভা ডিপ ক্লোনিং লাইব্রেরি' ...
গিলাইম

2
@ লুডিয়াই এই newInstance()পদ্ধতিটি ব্যবহার করুন এবং নির্মাতা Yumগভীর অনুলিপি বা অগভীর অনুলিপি করবেন?
গিক

9

সংস্করণ 2.07 যেহেতু ক্রিয়ো অগভীর / গভীর ক্লোনিং সমর্থন করে :

Kryo kryo = new Kryo();
SomeClass someObject = ...
SomeClass copy1 = kryo.copy(someObject);
SomeClass copy2 = kryo.copyShallow(someObject);

ক্রিও দ্রুত, তাদের পৃষ্ঠার এবং এর পৃষ্ঠায় আপনি সংস্থাগুলির একটি তালিকা পেতে পারেন যা এটি উত্পাদন করে এটি ব্যবহার করে।


5

মেমরিতে এক্সস্ট্রিম থেকে এক্সএমএল / থেকে এক্সএমএল ব্যবহার করুন। অত্যন্ত দ্রুত এবং প্রায় দীর্ঘ সময় ধরে ছিল এবং শক্তিশালী হচ্ছে। অবজেক্টগুলিকে সিরিয়ালাইজ করার দরকার নেই এবং আপনার প্রতিবিম্ব ব্যবহার নেই (যদিও এক্সস্ট্রিম রয়েছে) does এক্সস্ট্রিমগুলি একই পদার্থকে নির্দেশ করে এমন ভেরিয়েবলগুলি সনাক্ত করতে পারে এবং ঘটনাক্রমে ঘটনার দুটি সম্পূর্ণ অনুলিপি তৈরি করে না। এর মতো অনেকগুলি বিবরণ বছরের পর বছর ধরে ছড়িয়ে পড়েছে। আমি এটি বেশ কয়েক বছর ধরে ব্যবহার করেছি এবং এটি এখনও যায়। এটি আপনি কল্পনা করতে পারেন হিসাবে ব্যবহার করা প্রায় সহজ।

new XStream().toXML(myObj)

অথবা

new XStream().fromXML(myXML)

ক্লোন করতে,

new XStream().fromXML(new XStream().toXML(myObj))

আরও সংক্ষেপে:

XStream x = new XStream();
Object myClone = x.fromXML(x.toXML(myObj));

3

জটিল অবজেক্টের জন্য এবং যখন পারফরম্যান্স তাত্পর্যপূর্ণ না হয় আমি জসন টেক্সটে অবজেক্টটি সিরিয়ালাইজ করার জন্য জিএসএন ব্যবহার করি , তারপরে নতুন অবজেক্টটি পেতে পাঠ্যকে ডিসস্রায়ালাইজ করব।

প্রতিচ্ছবি ভিত্তিক জিএসসন বেশিরভাগ ক্ষেত্রে কাজ করবে, transientক্ষেত্রগুলি অনুলিপি করা হবে না এবং কারণের সাথে বিজ্ঞপ্তি রেফারেন্স সহ বস্তুগুলি StackOverflowError

public static <ObjectType> ObjectType Copy(ObjectType AnObject, Class<ObjectType> ClassInfo)
{
    Gson gson = new GsonBuilder().create();
    String text = gson.toJson(AnObject);
    ObjectType newObject = gson.fromJson(text, ClassInfo);
    return newObject;
}
public static void main(String[] args)
{
    MyObject anObject ...
    MyObject copyObject = Copy(o, MyObject.class);

}

2

নির্ভর করে।

গতির জন্য, ডিআইওয়াই ব্যবহার করুন। বুলেটপ্রুফের জন্য, প্রতিবিম্ব ব্যবহার করুন।

বিটিডাব্লু, সিরিয়ালাইজেশন রিফেলের মতো নয়, কারণ কিছু বস্তু ওভাররাইড সিরিয়ালাইজেশন পদ্ধতি (রিডওজেক্ট / রাইটওজেক্ট) সরবরাহ করতে পারে এবং সেগুলি বাগী হতে পারে


1
প্রতিবিম্ব বুলেট প্রুফ নয়: এটি এমন পরিস্থিতিতে বাধতে পারে যেখানে আপনার ক্লোন করা বস্তুটি আপনার উত্সের সাথে রেফারেন্স রেখেছে ... উত্স পরিবর্তিত হলে ক্লোনটিও বদলে যাবে!
Guillaume,

1

আমি DIY উপায়ে সুপারিশ করব যা একটি ভাল হ্যাশকোড () এবং সমান () পদ্ধতির সাথে একত্রীকরণের সাথে ইউনিট পরীক্ষায় প্রমাণ করার পক্ষে সহজ হবে।


ঠিক আছে, এই জাতীয় ডামি কোড তৈরি করার সময় অলস আমাকে প্রচুর পরিমাণে ডেকে আনে। তবে এটি দেখতে বুদ্ধিমান পথের মতো দেখাচ্ছে ...
গিলাইলে

2
আমরা দুঃখিত, কিন্তু, DIY যেতে উপায় কেবলমাত্র যদি অন্য কোন সমাধান you..which জন্য উপযুক্ত হয় প্রায় না
Bozho

1

আমি অবজেক্টক্লোন () কে ওভাররাইড করার পরামর্শ দিচ্ছি, প্রথমে সুপারক্লোন () কে কল করুন এবং আপনার রেফ অনুলিপি করতে চান এমন সমস্ত রেফারেন্সে কল রেফ = রেফক্লোন () ছাড়াই। এটি কমবেশি এটি নিজেই যান তবে কিছুটা কম কোডিং দরকার।


2
এটি (ভাঙ্গা) ক্লোন পদ্ধতিটির অনেকগুলি সমস্যার মধ্যে একটি: একটি শ্রেণি শ্রেণিবিন্যাসে আপনাকে সর্বদা সুপারক্লোন () কল করতে হবে, যা সহজেই ভুলে যেতে পারে, এজন্যই আমি একটি অনুলিপি নির্মাণকারীকে ব্যবহার করতে পছন্দ করব।
হেল্পারমোথড

0

গভীর ক্লোনিংয়ের জন্য প্রতিটি ক্লাসে সিরিয়ালাইজেবল বাস্তবায়ন আপনি এর মতো ক্লোন করতে চান

public static class Obj implements Serializable {
    public int a, b;
    public Obj(int a, int b) {
        this.a = a;
        this.b = b;
    }
}

এবং তারপরে এই ফাংশনটি ব্যবহার করুন:

public static Object deepClone(Object object) {
    try {
        ByteArrayOutputStream baOs = new ByteArrayOutputStream();
        ObjectOutputStream oOs = new ObjectOutputStream(baOs);
        oOs.writeObject(object);
        ByteArrayInputStream baIs = new ByteArrayInputStream(baOs.toByteArray());
        ObjectInputStream oIs = new ObjectInputStream(baIs);
        return oIs.readObject();
    }
    catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

এটার মত: Obj newObject = (Obj)deepClone(oldObject);

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