در این مقاله توضیح خواهیم داد که سریال سازی چیست و چگونه در جاوا کار می کند.
شکل 1. نمایش گرافیکی Threads
جریان ها عمدتاً به دو نوع تقسیم می شوند:
معرفی
سریال سازی شی، توانایی یک شی برای ذخیره یک کپی کامل از خود و هر شی دیگری که به آن ارجاع می دهد با استفاده از یک جریان خروجی (مثلاً به یک فایل خارجی) است. به این ترتیب، شی می تواند از نسخه سریال (ذخیره شده) کمی بعد در صورت نیاز دوباره ایجاد شود. سریال سازی اشیاء، ویژگی جدیدی است که در JDK 1.1 معرفی شده است، عملکردی را برای تبدیل گروه ها یا اشیاء منفرد، به یک جریان بیت یا آرایه بایت، برای ذخیره سازی یا انتقال از طریق شبکه فراهم می کند. و همانطور که گفته شد، یک جریان بیت معین یا آرایه بایت را می توان دوباره به اشیاء جاوا تبدیل کرد. این عمدتا به لطف کلاس هاObjectInputStream
و به طور خودکار اتفاق می افتد ObjectOutputStream
. برنامه نویس ممکن است تصمیم بگیرد که این قابلیت را با پیاده سازی رابط Serializable
در هنگام ایجاد کلاس پیاده سازی کند. فرآیند سریالسازی به عنوان مارشال کردن شی نیز شناخته میشود، در حالی که سریالزدایی به عنوان unmarshaling شناخته میشود . سریال سازی مکانیزمی است که به یک شی اجازه می دهد تا یک کپی از خود و سایر اشیاء ارجاع شده توسط شی را در یک فایل خارجی با استفاده از ObjectOutputStream
. اشیاء ذخیره شده می توانند ساختارهای داده، نمودارها، اشیاء کلاس JFrame
یا هر شیء دیگری بدون توجه به نوع آنها باشند. در عین حال، سریالسازی اطلاعات مربوط به نوع شیء را ذخیره میکند تا بعداً، زمانی که از سریال خارج شد، از آن اطلاعات برای بازسازی نوع دقیق شی استفاده شود. بنابراین، سریالسازی قابلیتهای زیر را فراهم میکند:
- سیستمی برای ذخیره اشیاء، به عنوان مثال: ذخیره خصوصیات آنها در یک فایل خارجی، روی دیسک یا پایگاه داده.
- سیستم تماس رویه از راه دور.
- یک سیستم توزیع شی، به عنوان مثال، در اجزای نرم افزاری مانند COM، COBRA.
- سیستمی برای شناسایی تغییرات داده های متغیر در طول زمان.
جریان ها:
هر برنامه ای باید داده های خود را در یک محل ذخیره یا لوله بنویسد و هر برنامه باید داده ها را از یک لوله یا محل ذخیره بخواند. در جاوا، به این کانالها که برنامهها در آن مینویسند و از آنها دادهها را میخوانند، Streams (Stream
) میگویند .
- کلاس های جریان بایتی به نام *Streams
- کلاس های جریان کاراکتر به نام *Reader و *Writer
ماندگاری
ماندگاری شی، توانایی یک شی برای زنده ماندن یا به عبارت دیگر، "بقا" در اجرای یک برنامه است. این بدان معنی است که هر شیئی که در زمان اجرا ایجاد شده باشد، هر زمان که دیگر از آن شیء استفاده نشود، توسط روبنده JVM از بین می رود. اما اگر Persistence API پیادهسازی شود، این اشیاء توسط جاروبرقی JVM از بین نمیروند، در عوض به آنها اجازه داده میشود که «زندگی کنند»، که دسترسی به آنها را در دفعات بعدی راهاندازی برنامه ممکن میسازد. به عبارت دیگر، ماندگاری به این معنی است که یک شیء، مستقل از طول عمر برنامه ای که در حال اجرا است، یک عمر وجود دارد. یکی از راههای پیادهسازی Persistence این است که اشیاء را در جایی در یک فایل یا پایگاه داده خارجی ذخیره کنید و سپس با استفاده از آن فایلها یا پایگاه داده به عنوان منبع، آنها را در زمان دیگری بازیابی کنید. اینجاست که سریال سازی مطرح می شود. تا زمانی که JVM در حال اجرا باشد، هر شی غیر پایداری وجود دارد. اشیاء سریال شده به سادگی اشیایی هستند که به جریان تبدیل می شوند، که سپس در یک فایل خارجی ذخیره می شوند یا برای ذخیره سازی و بازیابی از طریق شبکه منتقل می شوند.پیاده سازی رابط Serializable
هر کلاسی باید یک رابطjava.io.Serializable
برای سریال سازی اشیاء آن کلاس پیاده سازی کند. این رابط Serializable
هیچ متد ندارد و فقط کلاس را علامت گذاری می کند تا بتوان آن را به عنوان سریال پذیر شناسایی کرد. فقط فیلدهای یک شی کلاس سریالی را می توان ذخیره کرد. متدها یا سازنده ها به عنوان بخشی از جریان سریال ذخیره نمی شوند. اگر هر شی به عنوان یک مرجع به یک شی دیگر عمل کند، در صورتی که کلاس آن شیء رابط را پیاده سازی کند، فیلدهای آن شی نیز سریالی می شوند Serializable
. به عبارت دیگر، نمودار این شیء به دست آمده کاملاً قابل سریال سازی است. گراف شی شامل درخت یا ساختاری از فیلدهای یک شی و اشیاء فرعی آن است. دو کلاس اصلی که به پیاده سازی اینترفیس کمک می کنند Seriliazable
:
ObjectInputStream
ObjectOutputStream
import java.io.*;
public class RandomClass implements Serializable {
// Генерация рандомного значения
private static int r() {
return (int)(Math.random() * 10);
}
private int data[];
// Конструктор
public RandomClass() {
datafile = new int[r()];
for (int i=0; i<datafile.length; i++)
datafile[i]=r();
}
public void printout() {
System.out.println("This RandomClass has "+datafile.length+" random integers");
for (int i=0; i<datafile.length; i++) {
System.out.print(datafile[i]+":");
System.out.println();
}
}
در کد بالا کلاسی ایجاد می شود که قابل سریال سازی است زیرا "علامت گذاری شده" توسط رابط سریال سازی. کلاس هنگام ایجاد یک نمونه از آن، آرایه ای از اعداد صحیح تصادفی ایجاد می کند. کد زیر توانایی نوشتن اشیاء در یک جریان را با استفاده از ObjectOutputStream
. این برنامه دارای آرایه ای از اعداد صحیح است، اما برای سریال سازی، ما مجبور نیستیم روی اشیاء داخلی آن تکرار کنیم. رابط Seriliazable
به طور خودکار از این کار مراقبت می کند. لیست 2. یک مثال ساده از سریال سازی اشیاء برای خروجی به یک فایل
import java.io.*;
import java.util.*;
public class OutSerialize {
public static void main (String args[]) throws IOException {
RandomClass rc1 = new RandomClass();
RandomClass rc2 = new RandomClass();
//создание цепи потоков с потоком вывода an object в конце
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("objects.dat"));
Date now = new Date(System.currentTimeMillis());
//java.util.* был импортирован для использования класса Date
out.writeObject(now);
out.writeObject(rc1);
out.writeObject(rc2);
out.close();
System.out.println("I have written:");
System.out.println("A Date object: "+now);
System.out.println("Two Group of randoms");
rc1.printout();
rc2.printout();
}
}
کد زیر قابلیت های کلاس را نشان می دهد ObjectInputStream
که داده های سریال شده را از یک فایل خارجی در یک برنامه می خواند. توجه داشته باشید که اشیاء به همان ترتیبی که در فایل نوشته شده اند خوانده می شوند. فهرست 3. خواندن اشیاء سریال یا Deserializing
import java.io.*;
import java.util.*;
public class InSerialize {
public static void main (String args[]) throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream (new FileInputStream("objects.dat"));
Date d1 = (Date)in.readObject();
RandomClass rc1 = (RandomClass)in.readObject();
RandomClass rc2 = (RandomClass)in.readObject();
System.out.println("I have read:");
System.out.println("A Date object: "+d1);
System.out.println("Two Group of randoms");
rc1.printout();
rc2.printout();
}
}
تقریباً تمام کلاسهای جاوا، از جمله کلاسهای AWT، قابل سریالسازی هستند. یک قاب که یک پنجره است شامل مجموعه ای از اجزای گرافیکی است. اگر فریم سریالی باشد، موتور سریال سازی به این موضوع رسیدگی می کند و تمام اجزا و داده های آن (موقعیت، محتوا و غیره) را سریال می کند. برخی از اشیاء کلاس جاوا را نمی توان سریال سازی کرد زیرا حاوی داده هایی هستند که به منابع زودگذر سیستم عامل ارجاع می دهند. به عنوان مثال کلاس ها java.io.FileInputStream
و java.lang.Thread
. اگر یک شی حاوی ارجاعاتی به عناصر غیرقابل سریالسازی باشد، کل عملیات سریالسازی با شکست مواجه میشود و یک استثنا ایجاد میشود NotSerializableException
. اگر هر شی به مرجعی از یک شی غیر سریالی اشاره دارد، می توان آن را با استفاده از کلمه کلیدی گذرا سریال کرد . فهرست 4. ایجاد اشیاء قابل سریال سازی با استفاده از کلمه کلیدی گذرا
public class Sclass implements Serializable{
public transient Thread newThread;
//помните, что поток(поток параллельного исполнения) по умолчанию не сериализуемый класс
private String studentID;
private int sum;
}
امنیت در سریال سازی
سریال سازی یک کلاس در جاوا شامل ارسال تمام داده های آن به یک فایل یا پایگاه داده خارجی از طریق یک جریان است. ما می توانیم داده هایی را که هر زمان که بخواهیم سریال سازی می شوند محدود کنیم. دو راه برای انجام این کار وجود دارد:- هر پارامتر کلاسی که بهعنوان گذرا اعلام میشود ، سریالسازی نمیشود (بهطور پیشفرض، تمام پارامترهای کلاس سریالسازی میشوند)
- یا هر پارامتر کلاسی که میخواهیم سریال کنیم با یک تگ مشخص میشود
Externalizable
(به طور پیشفرض، هیچ پارامتری سریالسازی نمیشود).
ObjectOutputStream
یک شیء، اگر فیلد داده گذرا علامت گذاری شده باشد، فیلد داده با . مثلا: private transient String password
. از طرف دیگر، برای اعلام صریح دادههای یک شی بهعنوان سریالپذیر، باید کلاس را بهعنوان ExternalizablewriteExternal
صریحاً readExteranl
نوشتن و خواندن دادههای آن شی علامتگذاری کنیم.
نتیجه
ویژگی سریال سازی اشیا در بسیاری از سیستم های توزیع شده به عنوان راهی برای انتقال داده ها استفاده می شود. اما سریالسازی جزئیات پنهان را آشکار میکند، بنابراین اعتبار انواع دادههای انتزاعی را از بین میبرد، که به نوبه خود کپسولهسازی را از بین میبرد. در عین حال، خوب است بدانید که دادههای شی سریالسازی شده همان دادهای است که در شی اصلی و اصلی وجود داشت. این همچنین یک فرصت عالی برای پیاده سازی یک رابطObjectInputValidation
و لغو یک روش است validateObject()
، حتی اگر چندین خط کد استفاده شود. اگر شی پیدا نشد، میتوانیم یک استثنا را به درستی پرتاب کنیم InvalidObjectException
. مقاله اصلی: سریال سازی در جاوا چگونه کار می کند
GO TO FULL VERSION