আমি জানি এই প্রশ্নটি সত্যই পুরানো এবং এর একটি স্বীকৃত উত্তর রয়েছে, তবে এটি গুগল অনুসন্ধানে খুব বেশি পপ আপ হওয়ার সাথে সাথে আমি ভেবেছিলাম যে আমি ওজন করব কারণ কোনও সরবরাহিত উত্তর তিনটি ক্ষেত্রে গুরুত্বপূর্ণ বিবেচনা করে না - আমার মনে এইগুলির প্রাথমিক ব্যবহার পদ্ধতি। অবশ্যই, সমস্ত অনুমান করে যে কাস্টম সিরিয়ালাইজেশন ফর্ম্যাটটির আসলে প্রয়োজন আছে।
উদাহরণস্বরূপ সংগ্রহের ক্লাস নিন। কোনও লিঙ্কযুক্ত তালিকার ডিফল্ট সিরিয়ালাইজেশন বা বিএসটি-র ফলাফলের ফলে খুব অল্প পারফরম্যান্স লাভের সাথে স্থানের বিশাল ক্ষতি হ'ল কেবলমাত্র উপাদানগুলিকে ক্রমবর্ধমানের সাথে তুলনা করে। এটি আরও সত্য যদি কোনও সংগ্রহ কোনও প্রক্ষেপণ বা দৃষ্টিভঙ্গি হয় - এটির সর্বজনীন এপিআই দ্বারা প্রকাশের চেয়ে বৃহত্তর কাঠামোর রেফারেন্স রাখে।
সিরিয়ালযুক্ত অবজেক্টের যদি অপরিবর্তনীয় ক্ষেত্র থাকে যা কাস্টম সিরিয়ালাইজেশন প্রয়োজন, এর মূল সমাধানটি writeObject/readObject
অপর্যাপ্ত, কারণ লিখিত স্ট্রিমের অংশটি পড়ার আগে ডিসরিয়ালাইজড অবজেক্ট তৈরি করা হয় writeObject
। একটি লিঙ্কযুক্ত তালিকার এই সর্বনিম্ন বাস্তবায়ন নিন:
public class List<E> extends Serializable {
public final E head;
public final List<E> tail;
public List(E head, List<E> tail) {
if (head==null)
throw new IllegalArgumentException("null as a list element");
this.head = head;
this.tail = tail;
}
//methods follow...
}
এই কাঠামোটি head
প্রতিটি লিঙ্কের ক্ষেত্রটি পুনরাবৃত্তভাবে লিখে একটি null
মান অনুসরণ করে ক্রমিক করা যেতে পারে । এই ধরণের ফর্ম্যাটটি deserial করা তবে অসম্ভব হয়ে ওঠে: readObject
সদস্য ক্ষেত্রের মান (এখন নির্ধারিত null
) পরিবর্তন করতে পারে না । এখানে writeReplace
/ readResolve
জুটি আসুন :
private Object writeReplace() {
return new Serializable() {
private transient List<E> contents = List.this;
private void writeObject(ObjectOutputStream oos) {
List<E> list = contents;
while (list!=null) {
oos.writeObject(list.head);
list = list.tail;
}
oos.writeObject(null);
}
private void readObject(ObjectInputStream ois) {
List<E> tail = null;
E head = ois.readObject();
if (head!=null) {
readObject(ois); //read the tail and assign it to this.contents
this.contents = new List<>(head, this.contents)
}
}
private Object readResolve() {
return this.contents;
}
}
}
আমি দুঃখিত যদি উপরের উদাহরণটি সংকলন না করে (বা কাজ করে) তবে আশা করি এটি আমার বক্তব্যটি বর্ণনা করার পক্ষে যথেষ্ট। আপনি যদি মনে করেন এটি খুব সুদূরপ্রসারী উদাহরণ, দয়া করে মনে রাখবেন যে অনেকগুলি কার্যকরী ভাষা JVM- এ চলে এবং তাদের ক্ষেত্রে এই পদ্ধতিটি অপরিহার্য হয়ে ওঠে।
আমরা যতটা লিখেছি তার চেয়ে আমরা আলাদা ক্লাসের কোনও অবজেক্টকে ডিসরিয়ালাইজ করতে পারি ObjectOutputStream
। java.util.List
তালিকার প্রয়োগের মতো মতামতগুলির ক্ষেত্রে এটি হবে যা দীর্ঘ থেকে কোনও স্লাইস প্রকাশ করে ArrayList
। স্পষ্টতই, পুরো ব্যাকিং লিস্টকে সিরিয়ালাইজ করা একটি খারাপ ধারণা এবং আমাদের কেবল দেখা স্লাইস থেকে উপাদানগুলি লেখা উচিত। কেন তবে এটিকে থামান এবং ডিসিরিয়ালাইজেশন করার পরে অব্যর্থ স্তরের দিকনির্দেশনা রাখেন? আমরা কেবল স্ট্রিমের উপাদানগুলিকে একটিতে পড়তে ArrayList
পারি এবং এটি আমাদের ভিউ ক্লাসে মোড়কের পরিবর্তে সরাসরি ফিরিয়ে দিতে পারি।
বিকল্পভাবে, সিরিয়ালাইজেশনে উত্সর্গীকৃত অনুরূপ প্রতিনিধি শ্রেণি নকশা পছন্দ হতে পারে। একটি ভাল উদাহরণ হ'ল আমাদের সিরিয়ালাইজেশন কোডটি পুনরায় ব্যবহার করা। উদাহরণস্বরূপ, যদি আমাদের একটি বিল্ডার ক্লাস থাকে (স্ট্রিংয়ের জন্য স্ট্রিংবিল্ডারের অনুরূপ), আমরা সিরিয়ালাইজেশন ডেলিগেট লিখতে পারি যা কোনও সংগ্রহকে প্রবাহে খালি বিল্ডার লিখে সিরিয়ালাইজ করে, তারপরে সংগ্রহের আকার এবং উপাদানগুলির সংকলনের দ্বারা পুনরুদ্ধারকারী দ্বারা ফিরে আসে। ডেসারিয়ালাইজেশনটিতে বিল্ডারকে পড়া, পরবর্তীকালে সমস্ত পাঠক উপাদান যুক্ত করা এবং build()
প্রতিনিধিদের কাছ থেকে ফাইনালের ফলাফল ফিরিয়ে দেওয়া অন্তর্ভুক্ত থাকে readResolve
। সেক্ষেত্রে আমাদের কেবল সংগ্রহক্রমের শ্রেণিবিন্যাসের মূল শ্রেণিতেই সিরিয়ালকরণ বাস্তবায়ন করতে হবে এবং বর্তমান বা ভবিষ্যতের বাস্তবায়নগুলি থেকে কোনও অতিরিক্ত কোডের প্রয়োজন হবে না, যদি তারা বিমূর্ত প্রয়োগ করে iterator()
এবংbuilder()
পদ্ধতি (একই ধরণের সংগ্রহ পুনরুদ্ধার করার জন্য আধুনিক - যা নিজেই খুব কার্যকর বৈশিষ্ট্য হবে)। অন্য উদাহরণটি হ'ল আমরা কোন কোডটি পুরোপুরি নিয়ন্ত্রণ করি না - এমন একটি শ্রেণিবদ্ধ শ্রেণিবদ্ধতা রয়েছে - একটি তৃতীয় পক্ষের লাইব্রেরি থেকে আমাদের বেস শ্রেণি (এস) এমন অনেকগুলি ব্যক্তিগত ক্ষেত্র থাকতে পারে যার সম্পর্কে আমরা কিছুই জানিনা এবং যা একটি সংস্করণ থেকে অন্য সংস্করণে পরিবর্তিত হতে পারে আমাদের সিরিয়ালযুক্ত বস্তু সেক্ষেত্রে ডিজিটালাইজেশনে ডেটা লিখতে এবং বস্তুটিকে ম্যানুয়ালি পুনর্নির্মাণ করা নিরাপদ হবে।
String.CaseInsensitiveComparator.readResolve()