ডিপ অবজেক্ট কপি ফাংশন বাস্তবায়ন করা কিছুটা কঠিন। আসল অবজেক্টটি নিশ্চিত করার জন্য আপনি কী পদক্ষেপ গ্রহণ করেছেন এবং ক্লোন করা কোনও রেফারেন্স ভাগ করে নিচ্ছে?
ডিপ অবজেক্ট কপি ফাংশন বাস্তবায়ন করা কিছুটা কঠিন। আসল অবজেক্টটি নিশ্চিত করার জন্য আপনি কী পদক্ষেপ গ্রহণ করেছেন এবং ক্লোন করা কোনও রেফারেন্স ভাগ করে নিচ্ছে?
উত্তর:
একটি নিরাপদ উপায় হ'ল অবজেক্টটিকে সিরিয়ালাইজ করা, তারপরে ডিসরিয়ালাইজ করা। এটি নিশ্চিত করে যে সমস্ত কিছু একেবারে নতুন রেফারেন্স।
কীভাবে এটি দক্ষতার সাথে করা যায় সে সম্পর্কে একটি নিবন্ধ এখানে ।
ক্যাভেটস: ক্লাসগুলির পক্ষে সিরিয়ালকরণকে ওভাররাইড করা যেমন নতুন উদাহরণ তৈরি হয় না , যেমন সিঙ্গেলটনের ক্ষেত্রে for এছাড়াও আপনার ক্লাসগুলি সিরিয়ালাইজযোগ্য না হলে অবশ্যই এটি কাজ করে না।
কিছু লোক ব্যবহার বা ওভাররাইডিংয়ের কথা উল্লেখ করেছেন Object.clone()
। এটা করবেন না। Object.clone()
কিছু বড় সমস্যা রয়েছে এবং এর ব্যবহার বেশিরভাগ ক্ষেত্রে নিরুৎসাহিত করা হয়। সম্পূর্ণ উত্তরের জন্য দয়া করে জোশুয়া ব্লচের " কার্যকর জাভা " থেকে আইটেম 11 দেখুন । আমি বিশ্বাস করি আপনি নিরাপদে ব্যবহার করতে পারবেনObject.clone()
প্রাথমিকভাবে অ্যারেগুলিতে , তবে এগুলি ছাড়া ক্লোনটি সঠিকভাবে ব্যবহার এবং ওভাররাইড করা সম্পর্কে আপনার বিচার করা দরকার।
সিরিয়ালাইজেশনের উপর নির্ভর করে এমন স্কিমগুলি (এক্সএমএল বা অন্যথায়) ক্লডজি।
এখানে কোন সহজ উত্তর নেই। আপনি যদি কোনও বস্তুর গভীর অনুলিপি করতে চান তবে আপনাকে অবশ্যই অবজেক্টের গ্রাফটি অতিক্রম করতে হবে এবং প্রতিটি শিশুকে অবজেক্টের অনুলিপি নির্মাণকারী বা একটি স্থিতিশীল কারখানার পদ্ধতির মাধ্যমে স্পষ্টভাবে অনুলিপি করতে হবে যা ঘুরিয়ে শিশুর বস্তুটির গভীর অনুলিপি করে। অপরিবর্তনীয় (যেমন String
গুলি) অনুলিপি করার দরকার নেই। একদিকে যেমন, আপনার এই কারণে অপরিবর্তনীয়তার পক্ষে হওয়া উচিত।
আপনি ফাইল তৈরি না করে সিরিয়ালাইজেশন সহ একটি গভীর অনুলিপি তৈরি করতে পারেন।
আপনার অনুলিপিটির গভীর অনুলিপি করতে ইচ্ছুক আপনার প্রয়োজন implement serializable
। যদি ক্লাসটি চূড়ান্ত না হয় বা পরিবর্তন করা যায় না, ক্লাসটি প্রসারিত করুন এবং সিরিয়ালাইজযোগ্য প্রয়োগ করুন।
আপনার শ্রেণিকে বাইটের স্ট্রিমে রূপান্তর করুন:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(object);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();
বাইটের স্ট্রিম থেকে আপনার শ্রেণি পুনরুদ্ধার করুন:
ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
(Object) object = (Object) new ObjectInputStream(bais).readObject();
instance
এই ক্ষেত্রে নন-সিরিয়ালাইজযোগ্য শ্রেণীর সম্পত্তি কীভাবে সিরিয়ালাইজড, অ-সিরিয়ালাইজযোগ্য হবে ?
আপনি org.apache.commons.lang3.SerializationUtils.clone(T)
অ্যাপাচি কমন্স ল্যাং-এ ব্যবহার করে সিরিয়ালাইজেশন-ভিত্তিক গভীর ক্লোন করতে পারেন , তবে সতর্ক থাকুন — পারফরম্যান্সটি অত্যন্ত অসাধারণ।
সাধারণভাবে, অবজেক্ট গ্রাফের ক্লোনিংয়ের প্রয়োজনীয়তার জন্য প্রতিটি শ্রেণীর জন্য নিজের ক্লোন পদ্ধতি লিখতে ভাল অনুশীলন।
org.apache.commons.lang.SerializationUtils
গভীর অনুলিপি কার্যকর করার একটি উপায় হ'ল প্রতিটি সম্পর্কিত শ্রেণিতে অনুলিপি নির্মাণকারী যুক্ত করা। একটি অনুলিপি নির্মাণকারী তার একক যুক্তি হিসাবে 'এটি' এর উদাহরণ গ্রহণ করে এবং এটি থেকে সমস্ত মান অনুলিপি করে। বেশ কিছু কাজ, তবে বেশ সোজা এবং নিরাপদ।
সম্পাদনা: নোট করুন যে ক্ষেত্রগুলি পড়তে আপনার অ্যাকসেসর পদ্ধতি ব্যবহার করার দরকার নেই। আপনি সরাসরি সমস্ত ক্ষেত্র অ্যাক্সেস করতে পারেন কারণ উত্স উদাহরণটি সর্বদা অনুলিপি হিসাবে অনুলিপি তৈরির সাথে থাকে। স্পষ্টতই তবে তা উপেক্ষা করা যেতে পারে।
উদাহরণ:
public class Order {
private long number;
public Order() {
}
/**
* Copy constructor
*/
public Order(Order source) {
number = source.number;
}
}
public class Customer {
private String name;
private List<Order> orders = new ArrayList<Order>();
public Customer() {
}
/**
* Copy constructor
*/
public Customer(Customer source) {
name = source.name;
for (Order sourceOrder : source.orders) {
orders.add(new Order(sourceOrder));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
সম্পাদনা: নোট করুন যে অনুলিপি নির্মাণকারী ব্যবহার করার সময় আপনার অনুলিপি করা অবজেক্টটির রানটাইম ধরণের বিষয়টি জানতে হবে। উপরোক্ত পদ্ধতির সাহায্যে আপনি সহজেই একটি মিশ্র তালিকার অনুলিপি করতে পারবেন না (আপনি কিছু প্রতিবিম্ব কোড দিয়ে এটি করতে সক্ষম হতে পারেন)।
Toyota
আপনার কোডটি Car
গন্তব্য তালিকায় রাখবে। যথাযথ ক্লোনিংয়ের জন্য সাধারণত শ্রেণীর ভার্চুয়াল ফ্যাক্টরি পদ্ধতি সরবরাহ করা প্রয়োজন যার চুক্তিতে বলা হয়েছে যে এটি তার নিজস্ব শ্রেণীর একটি নতুন বস্তু ফিরিয়ে দেবে; অনুলিপি কন্ট্রাক্টর নিজেই protected
এটি নিশ্চিত হওয়া উচিত যে এটি কেবলমাত্র এমন অবজেক্ট তৈরি করতে ব্যবহার করা হবে যাঁর সুনির্দিষ্ট প্রবন্ধটি অনুলিপি করা হচ্ছে)
আপনি এমন একটি লাইব্রেরি ব্যবহার করতে পারেন যাতে একটি সাধারণ এপিআই থাকে এবং প্রতিবিম্বের সাথে তুলনামূলকভাবে দ্রুত ক্লোনিং সম্পাদন করে (সিরিয়ালাইজেশন পদ্ধতির চেয়ে দ্রুত হওয়া উচিত)।
Cloner cloner = new Cloner();
MyClass clone = cloner.deepClone(o);
// clone is a deep-clone of o
অ্যাপাচি কমন্স একটি বস্তুর গভীর ক্লোন করার জন্য দ্রুত উপায় সরবরাহ করে।
My_Object object2= org.apache.commons.lang.SerializationUtils.clone(object1);
এক্সস্ট্রিম এই জাতীয় দৃষ্টান্তগুলিতে সত্যই কার্যকর। ক্লোনিং করার জন্য এখানে একটি সাধারণ কোড
private static final XStream XSTREAM = new XStream();
...
Object newObject = XSTREAM.fromXML(XSTREAM.toXML(obj));
একটি খুব সহজ এবং সহজ পদ্ধিতি হ'ল জ্যাকসন জেএসএনকে জাসন জেজেট অবজেক্টকে জেএসএন-তে সিরিয়ালাইজ করতে এবং এটি আবার পড়তে।
জন্য স্প্রিং ফ্রেমওয়ার্ক ব্যবহারকারীদের। ক্লাস ব্যবহার org.springframework.util.SerializationUtils
:
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T object) {
return (T) SerializationUtils.deserialize(SerializationUtils.serialize(object));
}
জটিল অবজেক্টের জন্য এবং যখন পারফরম্যান্স তাত্পর্যপূর্ণ না হয় আমি জসনের মতো একটি জেসন লাইব্রেরি ব্যবহার করি সাথে বস্তুটিকে সিরিয়ালাইজ করতে , তারপরে নতুন অবজেক্টটি পাওয়ার জন্য পাঠ্যকে করা।
প্রতিচ্ছবি ভিত্তিক জিএসসন বেশিরভাগ ক্ষেত্রে কাজ করবে, transient
ক্ষেত্রগুলি অনুলিপি করা হবে না এবং কারণের সাথে বিজ্ঞপ্তি রেফারেন্স সহ বস্তুগুলি StackOverflowError
।
public static <T> T copy(T anObject, Class<T> classInfo) {
Gson gson = new GsonBuilder().create();
String text = gson.toJson(anObject);
T newObject = gson.fromJson(text, classInfo);
return newObject;
}
public static void main(String[] args) {
String originalObject = "hello";
String copiedObject = copy(originalObject, String.class);
}
এক্সস্ট্রিম ( http://x-stream.github.io/ ) ব্যবহার করুন । এমনকি আপনি টীকাগুলির মাধ্যমে কোন বৈশিষ্ট্য উপেক্ষা করতে পারবেন বা এক্সস্ট্রিম শ্রেণিতে সম্পত্তিটির নাম স্পষ্ট করে উল্লেখ করতে পারবেন তা আপনি নিয়ন্ত্রণ করতে পারেন। তদুপরি আপনার ক্লোনযোগ্য ইন্টারফেস প্রয়োগ করার দরকার নেই।
গভীর কপি শুধুমাত্র প্রতিটি শ্রেণীর সম্মতিতে করা যেতে পারে। আপনার যদি শ্রেণি শ্রেণিবিন্যাসের নিয়ন্ত্রণ থাকে তবে আপনি ক্লোনযোগ্য ইন্টারফেস প্রয়োগ করতে এবং ক্লোন পদ্ধতিটি প্রয়োগ করতে পারেন। অন্যথায় একটি গভীর অনুলিপি নিরাপদে করা অসম্ভব কারণ বস্তুটি অ-ডেটা সংস্থানগুলিও ভাগ করে নিচ্ছে (যেমন ডাটাবেস সংযোগ)। সাধারণভাবে তবে গভীর অনুলিপি জাভা পরিবেশে খারাপ অভ্যাস হিসাবে বিবেচিত হয় এবং উপযুক্ত নকশা অনুশীলনের মাধ্যমে এড়ানো উচিত।
import com.thoughtworks.xstream.XStream;
public class deepCopy {
private static XStream xstream = new XStream();
//serialize with Xstream them deserialize ...
public static Object deepCopy(Object obj){
return xstream.fromXML(xstream.toXML(obj));
}
}
BeanUtils গভীর ক্লোনিং মটরশুটি একটি সত্যিই ভাল কাজ করে।
BeanUtils.cloneBean(obj);
1)
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;
}
}
2)
// (1) create a MyPerson object named Al
MyAddress address = new MyAddress("Vishrantwadi ", "Pune", "India");
MyPerson al = new MyPerson("Al", "Arun", address);
// (2) make a deep clone of Al
MyPerson neighbor = (MyPerson)deepClone(al);
এখানে আপনার মাইপারসন এবং মাইএড্রেস ক্লাসকে অবশ্যই সিরিলেজযোগ্য ইন্টারফেস প্রয়োগ করতে হবে
জ্যাকসন ব্যবহার করে অবজেক্টটি সিরিয়ালাইজ এবং ডিজাইরিয়াল করা হচ্ছে। এই বাস্তবায়নের জন্য সিরিয়ালাইজেবল শ্রেণি প্রয়োগের জন্য বস্তুর প্রয়োজন হয় না।
<T> T clone(T object, Class<T> clazzType) throws IOException {
final ObjectMapper objMapper = new ObjectMapper();
String jsonStr= objMapper.writeValueAsString(object);
return objMapper.readValue(jsonStr, clazzType);
}