JavaRush /Java blogi /Random-UZ /Serializatsiya avvalgidek. 1-qism
articles
Daraja

Serializatsiya avvalgidek. 1-qism

Guruhda nashr etilgan
Bir qarashda seriallashtirish arzimas jarayondek tuyuladi. Haqiqatan ham, nima oddiyroq bo'lishi mumkin? Interfeysni amalga oshirish uchun sinfni e'lon qildi java.io.Serializable- va bu. Siz sinfni muammosiz ketma-ketlashtirishingiz mumkin. Serializatsiya avvalgidek.  1-1-qismNazariy jihatdan, bu haqiqat. Amalda juda ko'p nozikliklar mavjud. Ular ishlash, seriyadan chiqarish, sinf xavfsizligi bilan bog'liq. Va yana ko'p jihatlar bilan. Bunday nozikliklar muhokama qilinadi. Ushbu maqolani quyidagi qismlarga bo'lish mumkin:
  • Mexanizmlarning nozik tomonlari
  • Nima uchun kerak?Externalizable
  • Ishlash
  • lekin boshqa tomondan
  • Ma'lumotlar xavfsizligi
  • Ob'ektni ketma-ketlashtirishSingleton
Keling, birinchi qismga o'tamiz -

Mexanizmlarning nozik tomonlari

Birinchidan, tezkor savol. Ob'ektni seriyali qilishning necha yo'li mavjud? Amaliyot shuni ko'rsatadiki, ishlab chiquvchilarning 90% dan ortig'i bu savolga taxminan bir xil javob berishadi (so'zgacha) - faqat bitta yo'l bor. Ayni paytda ulardan ikkitasi bor. Ikkinchisini hamma ham eslamaydi, uning xususiyatlari haqida tushunarli narsa deyish u yoqda tursin. Xo'sh, bu usullar nima? Birinchisini hamma eslaydi. Bu allaqachon aytib o'tilgan dastur java.io.Serializableva hech qanday kuch talab qilmaydi. Ikkinchi usul ham interfeysni amalga oshirishdir, lekin boshqacha: java.io.Externalizable. Bundan farqli o'laroq java.io.Serializable, u amalga oshirilishi kerak bo'lgan ikkita usulni o'z ichiga oladi - writeExternal(ObjectOutput)va readExternal(ObjectInput). Ushbu usullar ketma-ketlashtirish/deserializatsiya mantig'ini o'z ichiga oladi. Izoh.Quyida men ba'zan standart sifatida amalga oshirish va kengaytirilgan holda amalga oshirish bilan ketma-ketlashtirishga Serializablemurojaat qilaman . ExternalizableBoshqaizoh. Men ataylab endi belgilash kabi standart seriyali boshqaruv variantlariga tegmayman readObjectva writeObject, chunki Menimcha, bu usullar biroz noto'g'ri. Ushbu usullar interfeysda aniqlanmagan Serializableva aslida cheklovlarni bartaraf etish va standart seriyalashni moslashuvchan qilish uchun yordam beradi. ExternalizableMoslashuvchanlikni ta'minlaydigan usullar, eng boshidanoq, ular ichiga o'rnatilgan . Keling, yana bir savol beraylik. dan foydalangan holda standart serializatsiya qanday ishlaydi java.io.Serializable? Va u Reflection API orqali ishlaydi. Bular. sinf maydonlar to'plami sifatida tahlil qilinadi, ularning har biri chiqish oqimiga yoziladi. Menimcha, bu operatsiya ishlash nuqtai nazaridan optimal emasligi aniq. Aniq qanchaligini keyinroq bilib olamiz. Yuqorida aytib o'tilgan ikkita ketma-ketlashtirish usullari o'rtasida yana bir katta farq bor. Ya'ni, seriyadan chiqarish mexanizmida. Foydalanilganda Serializableseriyani yo'qotish quyidagicha sodir bo'ladi: ob'ekt uchun xotira ajratiladi, shundan so'ng uning maydonlari oqim qiymatlari bilan to'ldiriladi. Ob'ekt konstruktori chaqirilmaydi. Bu erda biz ushbu vaziyatni alohida ko'rib chiqishimiz kerak. OK, bizning sinfimiz seriyali. Va uning ota-onasi? To'liq ixtiyoriy! Bundan tashqari, agar siz sinfni meros qilib olgan bo'lsangiz Object- ota-onani ketma-ketlashtirib bo'lmaydi. ObjectVa biz sohalar haqida hech narsa bilmasak ham , ular bizning ota-onalar sinfimizda mavjud bo'lishi mumkin. Ularga nima bo'ladi? Ular serializatsiya oqimiga kirmaydi. Seriyadan chiqarishda ular qanday qiymatlarni oladilar? Keling, ushbu misolni ko'rib chiqaylik:
package ru.skipy.tests.io;

import java.io.*;

/**
 * ParentDeserializationTest
 *
 * @author Eugene Matyushkin aka Skipy
 * @since 05.08.2010
 */
public class ParentDeserializationTest {

    public static void main(String[] args){
        try {
            System.out.println("Creating...");
            Child c = new Child(1);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            c.field = 10;
            System.out.println("Serializing...");
            oos.writeObject(c);
            oos.flush();
            baos.flush();
            oos.close();
            baos.close();
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            System.out.println("Deserializing...");
            Child c1 = (Child)ois.readObject();
            System.out.println("c1.i="+c1.getI());
            System.out.println("c1.field="+c1.getField());
        } catch (IOException ex){
            ex.printStackTrace();
        } catch (ClassNotFoundException ex){
            ex.printStackTrace();
        }
    }

    public static class Parent {
        protected int field;
        protected Parent(){
            field = 5;
            System.out.println("Parent::Constructor");
        }
        public int getField() {
            return field;
        }
    }

    public static class Child extends Parent implements Serializable{
        protected int i;
        public Child(int i){
            this.i = i;
            System.out.println("Child::Constructor");
        }
        public int getI() {
            return i;
        }
    }
}
Bu shaffof - bizda seriyali bo'lmagan ota-klass va ketma-ketlashtiriladigan bolalar sinfi mavjud. Va bu sodir bo'ladi:
Creating...
Parent::Constructor
Child::Constructor
Serializing...
Deserializing...
Parent::Constructor
c1.i=1
c1.field=5
Ya'ni ketma-ketlikdan chiqarish vaqtida asosiy NON-seriyalashtirilmaydigan sinfning parametrlari bo'lmagan konstruktor deyiladi . Va agar bunday konstruktor bo'lmasa, deserializatsiya paytida xatolik yuz beradi. Biz seriyadan chiqarayotgan bola ob'ektining konstruktori, yuqorida aytib o'tilganidek, chaqirilmaydi. Foydalanishda standart mexanizmlar shunday yo'l tutadi Serializable. Uni qo'llashda Externalizablevaziyat boshqacha. Birinchidan, parametrsiz konstruktor chaqiriladi, so'ngra yaratilgan ob'ektda readExternal usuli chaqiriladi, u aslida uning barcha ma'lumotlarini o'qiydi. Shuning uchun, Externalizable interfeysini amalga oshiradigan har qanday sinf parametrsiz umumiy konstruktorga ega bo'lishi kerak! Bundan tashqari, bunday sinfning barcha avlodlari interfeysni amalga oshirish uchun ham ko'rib chiqilishi sababli Externalizable, ular ham parametrsiz konstruktorga ega bo'lishi kerak! Keling, oldinga boraylik. kabi maydon o'zgartiruvchisi mavjud transient. Bu shuni anglatadiki, bu maydon ketma-ketlashtirilmasligi kerak. Biroq, o'zingiz tushunganingizdek, ushbu ko'rsatma faqat standart seriyalash mexanizmiga ta'sir qiladi. Foydalanilganda, Externalizablehech kim bu maydonni ketma-ketlashtirishni, shuningdek, uni olib tashlashni bezovta qilmaydi. Agar maydon vaqtinchalik deb e'lon qilingan bo'lsa, u holda ob'ekt seriyadan chiqarilganda u standart qiymatni oladi. Yana bir juda nozik nuqta. Standart serializatsiya bilan modifikatorga ega bo'lgan maydonlar staticketma-ketlashtirilmaydi. Shunga ko'ra, seriyadan chiqarilgandan so'ng bu maydon o'z qiymatini o'zgartirmaydi. Albatta, amalga oshirish jarayonida Externalizablehech kim ushbu maydonni seriyali va seriyali holga keltirmaydi, lekin men buni qilmaslikni tavsiya qilaman, chunki bu nozik xatolarga olib kelishi mumkin. Modifikatorli maydonlar finalodatdagidek ketma-ketlashtiriladi. Bitta istisno - Externalizable-dan foydalanganda ularni seriyadan chiqarib bo'lmaydi. Chunki final-поляular konstruktorda ishga tushirilishi kerak va shundan keyin readExternal-da bu maydonning qiymatini o'zgartirish mumkin bo'lmaydi. Shunga ko'ra, agar siz -maydoniga ega bo'lgan ob'ektni ketma-ketlashtirishingiz kerak bo'lsa final, siz faqat standart serializatsiyadan foydalanishingiz kerak bo'ladi. Ko'pchilik bilmagan yana bir nuqta. Standart seriyalash sinfda maydonlarni e'lon qilish tartibini hisobga oladi. Har holda, oldingi versiyalarda shunday bo'lgan; Oracle ilovasining JVM 1.6 versiyasida tartib endi muhim emas, maydonning turi va nomi muhim. Usullarning tarkibi, odatda, maydonlar bir xil bo'lib qolishi mumkinligiga qaramasdan, standart mexanizmga ta'sir qilish ehtimoli juda katta. Buning oldini olish uchun quyidagi mexanizm mavjud. Interfeysni amalga oshiradigan har bir sinfga Serializablekompilyatsiya bosqichida yana bitta maydon qo'shiladi -private static final long serialVersionUID. Bu maydon ketma-ketlashtirilgan sinfning noyob versiya identifikatorini o'z ichiga oladi. U sinfning mazmuni - maydonlar, ularni e'lon qilish tartibi, usullari, ularni e'lon qilish tartibi asosida hisoblanadi. Shunga ko'ra, sinfdagi har qanday o'zgarish bilan bu maydon o'z qiymatini o'zgartiradi. Bu maydon sinf ketma-ketlashtirilganda oqimga yoziladi. Aytgancha, bu menga ma'lum bo'lgan yagona holat - staticmaydon seriyali bo'lganida. Seriyadan chiqarish vaqtida ushbu maydonning qiymati virtual mashinadagi sinf bilan solishtiriladi. Agar qiymatlar mos kelmasa, bunday istisno chiqariladi:
java.io.InvalidClassException: test.ser2.ChildExt;
    local class incompatible: stream classdesc serialVersionUID = 8218484765288926197,
                                   local class serialVersionUID = 1465687698753363969
Biroq, bu chekni chetlab o'tmasa, aldashning bir yo'li bor. Agar sinf maydonlari to'plami va ularning tartibi allaqachon aniqlangan bo'lsa, bu foydali bo'lishi mumkin, ammo sinf usullari o'zgarishi mumkin. Bunday holda, serializatsiya xavf ostida emas, lekin standart mexanizm o'zgartirilgan sinfning bayt-kodi yordamida ma'lumotlarni seriyadan chiqarishga ruxsat bermaydi. Lekin, aytganimdek, uni aldash mumkin. Ya'ni, sinfdagi maydonni qo'lda aniqlang private static final long serialVersionUID. Aslida, bu maydonning qiymati mutlaqo har qanday bo'lishi mumkin. Ba'zi odamlar uni kod o'zgartirilgan sanaga tenglashtirishni afzal ko'rishadi. Ba'zilar hatto 1 litrdan ham foydalanishadi. Standart qiymatni (ichki hisoblangan) olish uchun siz SDK-ga kiritilgan serialver yordam dasturidan foydalanishingiz mumkin. Shu tarzda aniqlangandan so'ng, maydonning qiymati o'rnatiladi, shuning uchun seriyani bekor qilishga har doim ruxsat beriladi. Bundan tashqari, 5.0 versiyasida hujjatlarda taxminan quyidagilar paydo bo'ldi: barcha ketma-ketlashtiriladigan sinflar ushbu maydonni aniq e'lon qilishlari tavsiya etiladi, chunki standart hisoblash sinf tuzilishi tafsilotlariga juda sezgir bo'lib, kompilyatorning bajarilishiga qarab farq qilishi mumkin, va shuning uchun kutilmagan InvalidClassExceptionoqibatlarga olib keladi. Bu maydonni deb e'lon qilish yaxshidir private, chunki u faqat e'lon qilingan sinfga tegishli. Modifikator spetsifikatsiyada ko'rsatilmagan bo'lsa-da. Keling, ushbu jihatni ko'rib chiqaylik. Aytaylik, bizda bu sinf tuzilishi mavjud:
public class A{
    public int iPublic;
    protected int iProtected;
    int iPackage;
    private int iPrivate;
}

public class B extends A implements Serializable{}
Boshqacha qilib aytganda, bizda seriyali bo'lmagan ota-onadan meros qilib olingan sinf mavjud. Bu sinfni seriyali qilish mumkinmi va buning uchun nima kerak? Ota-klassning o'zgaruvchilari bilan nima sodir bo'ladi? Javob bu. Ha, Bsiz sinfning namunasini ketma-ketlashtirishingiz mumkin. Buning uchun nima kerak? Lekin sinfda Aparametrlarsiz konstruktor publicyoki protected. Keyin, seriyani yo'q qilish vaqtida barcha sinf o'zgaruvchilari Aushbu konstruktor yordamida ishga tushiriladi. Sinf o'zgaruvchilari Bketma-ketlashtirilgan ma'lumotlar oqimidagi qiymatlar bilan ishga tushiriladi. Nazariy jihatdan, sinfda Bmen boshida aytib o'tgan usullarni aniqlash mumkin - readObjectva writeObject, - boshida sinf o'zgaruvchilari seriyasini (de-) , keyin esa mavjud o'zgaruvchilarni (de-) seriyalilashtirishni Bamalga oshirish kerak. in.defaultReadObject/out.defaultWriteObjectsinfdan A(bizning holimizda bular iPublic, iProtectedva iPackage, agar Bu bilan bir xil paketda bo'lsa A). Biroq, mening fikrimcha, buning uchun kengaytirilgan serializatsiyadan foydalanish yaxshiroqdir. Men to'xtalmoqchi bo'lgan navbatdagi nuqta - bu bir nechta ob'ektlarni ketma-ketlashtirish. Aytaylik, bizda quyidagi sinf tuzilishi mavjud:
public class A implements Serializable{
    private C c;
    private B b;
    public void setC(C c) {this.c = c;}
    public void setB(B b) {this.b = b;}
    public C getC() {return c;}
    public B getB() {return b;}
}
public class B implements Serializable{
    private C c;
    public void setC(C c) {this.c = c;}
    public C getC() {return c;}
}
public class C implements Serializable{
    private A a;
    private B b;
    public void setA(A a) {this.a = a;}
    public void setB(B b) {this.b = b;}
    public B getB() {return b;}
    public A getA() {return a;}
}
Serializatsiya avvalgidek.  1-2 qismAgar siz sinfning namunasini ketma-ketlashtirsangiz nima bo'ladi A? U sinfning bir nusxasi bo'ylab sudrab boradi B, bu esa o'z navbatida , hammasi boshlangan Cmisolga havolaga ega bo'lgan misol bo'ylab sudrab boradi. AShafqatsiz doira va cheksiz rekursiya? Yaxshiyamki, yo'q. Keling, quyidagi test kodini ko'rib chiqaylik:
// initiaizing
A a = new A();
B b = new B();
C c = new C();
// setting references
a.setB(b);
a.setC(c);
b.setC(c);
c.setA(a);
c.setB(b);
// serializing
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(a);
oos.writeObject(b);
oos.writeObject(c);
oos.flush();
oos.close();
// deserializing
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
A a1 = (A)ois.readObject();
B b1 = (B)ois.readObject();
C c1 = (C)ois.readObject();
// testing
System.out.println("a==a1: "+(a==a1));
System.out.println("b==b1: "+(b==b1));
System.out.println("c==c1: "+(c==c1));
System.out.println("a1.getB()==b1: "+(a1.getB()==b1));
System.out.println("a1.getC()==c1: "+(a1.getC()==c1));
System.out.println("b1.getC()==c1: "+(b1.getC()==c1));
System.out.println("c1.getA()==a1: "+(c1.getA()==a1));
System.out.println("c1.getB()==b1: "+(c1.getB()==b1));
Biz nima qilyapmiz? Biz sinflarning namunasini yaratamiz Ava B, Cularga bir-biriga havolalar beramiz va keyin ularning har birini ketma-ketlashtiramiz. Keyin biz ularni seriyadan chiqaramiz va bir qator tekshiruvlarni o'tkazamiz. Natijada nima bo'ladi:
a==a1: false
b==b1: false
c==c1: false
a1.getB()==b1: true
a1.getC()==c1: true
b1.getC()==c1: true
c1.getA()==a1: true
c1.getB()==b1: true
Xo'sh, bu testdan nimani o'rganishingiz mumkin? Birinchidan. Seriyadan chiqarilgandan keyin ob'ekt havolalari undan oldingi havolalardan farq qiladi. Boshqacha qilib aytadigan bo'lsak, serializatsiya/deserializatsiya paytida ob'ekt nusxalangan. Bu usul ba'zan ob'ektlarni klonlash uchun ishlatiladi. Ikkinchi xulosa muhimroq. O'zaro havolalarga ega bo'lgan bir nechta ob'ektlarni ketma-ketlashtirish/seriyadan chiqarishda, bu havolalar seriyadan chiqarilgandan keyin ham o'z kuchida qoladi. Boshqacha qilib aytadigan bo'lsak, agar ketma-ketlashtirishdan oldin ular bitta ob'ektga ishora qilgan bo'lsa, seriyadan chiqarishdan keyin ular bitta ob'ektga ham ishora qiladilar. Buni tasdiqlash uchun yana bir kichik test:
B b = new B();
C c = new C();
b.setC(c);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(b);
oos.writeObject(c);
oos.writeObject(c);
oos.writeObject(c);
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
B b1 = (B)ois.readObject();
C c1 = (C)ois.readObject();
C c2 = (C)ois.readObject();
C c3 = (C)ois.readObject();
System.out.println("b1.getC()==c1: "+(b1.getC()==c1));
System.out.println("c1==c2: "+(c1==c2));
System.out.println("c1==c3: "+(c1==c3));
Sinf ob'ektida Bsinf ob'ektiga havola mavjud C. Seriyalashtirilganda, bu sinf namunasi bilan birga ketma-ketlashtiriladi С, shundan so'ng c ning bir xil nusxasi uch marta ketma-ketlashtiriladi. Seriyadan chiqarilgandan keyin nima bo'ladi?
b1.getC()==c1: true
c1==c2: true
c1==c3: true
Ko'rib turganingizdek, barcha to'rtta seriyasizlashtirilgan ob'ektlar aslida bitta ob'ektni ifodalaydi - unga havolalar teng. Xuddi serializatsiyadan oldin bo'lgani kabi. Yana bir qiziqarli nuqta - agar biz bir vaqtning o'zida amalga oshirsak nima bo'ladi Externalizableva Serializable? Bu savoldagi kabi - fil va kit - kim kimni mag'lub qiladi? Yengadi Externalizable. Serializatsiya mexanizmi avval uning mavjudligini tekshiradi va shundan keyingina uning mavjudligini tekshiradi.Shunday Serializableqilib, agar amalga oshiruvchi B klassi SerializableA sinfidan meros bo'lsa, ExternalizableB sinfining maydonlari ketma-ketlashtirilmaydi. Oxirgi nuqta - meros. ni amalga oshiradigan sinfdan meros olayotganda Serializable, qo'shimcha harakatlar qilish kerak emas. Serializatsiya bolalar sinfiga ham taalluqlidir. ni amalga oshiradigan sinfdan meros olayotganda Externalizable, ota-klassning readExternal va writeExternal usullarini bekor qilishingiz kerak. Aks holda, bolalar sinfining maydonlari ketma-ketlashtirilmaydi. Bunday holda, siz ota-ona usullarini chaqirishni unutmasligingiz kerak, aks holda ota-ona maydonlari ketma-ketlashtirilmaydi. * * * Tafsilotlarni tugatganmiz. Biroq, biz to'xtalmagan bir masala borki, u global xarakterga ega. Aynan -

Nima uchun sizga Externalizable kerak?

Nima uchun bizga ilg'or serializatsiya kerak? Javob oddiy. Birinchidan, bu ko'proq moslashuvchanlikni beradi. Ikkinchidan, u ko'pincha ketma-ketlashtirilgan ma'lumotlar hajmi bo'yicha sezilarli daromad keltirishi mumkin. Uchinchidan, ishlash kabi jihat bor, biz quyida gaplashamiz . Moslashuvchanlik bilan hamma narsa aniq ko'rinadi. Darhaqiqat, biz ketma-ketlashtirish va seriyadan chiqarish jarayonlarini xohlagancha boshqarishimiz mumkin, bu bizni sinfdagi har qanday o'zgarishlardan mustaqil qiladi (yuqorida aytganimdek, sinfdagi o'zgarishlar seriyasizlashtirishga katta ta'sir ko'rsatishi mumkin). Shuning uchun, men hajmdagi daromad haqida bir necha so'z aytmoqchiman. Aytaylik, bizda quyidagi sinf mavjud:
public class DateAndTime{

  private short year;
  private byte month;
  private byte day;
  private byte hours;
  private byte minutes;
  private byte seconds;

}
Qolganlari ahamiyatsiz. Maydonlar int turida bo'lishi mumkin, ammo bu faqat misolning ta'sirini kuchaytiradi. Garchi aslida maydonlar intishlash sabablariga ko'ra kiritilishi mumkin. Har holda, gap aniq. Sinf sana va vaqtni bildiradi. Bu biz uchun birinchi navbatda seriallashtirish nuqtai nazaridan qiziq. Ehtimol, eng oson narsa oddiy vaqt tamg'asini saqlashdir. U uzun turdagi, ya'ni. ketma-ketlashtirilganda u 8 baytni oladi. Bundan tashqari, ushbu yondashuv komponentlarni bir qiymatga va orqaga aylantirish usullarini talab qiladi, ya'ni. - hosildorlikning yo'qolishi. Ushbu yondashuvning afzalligi 64 bitga sig'adigan mutlaqo aqldan ozgan sanadir. Bu xavfsizlikning katta chegarasi, ko'pincha haqiqatda kerak emas. Yuqorida berilgan sinf 2 + 5*1 = 7 baytni oladi. Bundan tashqari, sinf va 6 ta maydon uchun qo'shimcha xarajatlar. Ushbu ma'lumotlarni siqishning biron bir usuli bormi? Albatta. soniyalar va daqiqalar 0-59 oralig'ida, ya'ni. ularni ifodalash uchun 8 o‘rniga 6 bit yetarli. Soat – 0-23 (5 bit), kunlar – 0-30 (5 bit), oylar – 0-11 (4 bit). Jami, yilni hisobga olmagan holda hamma narsa - 26 bit. int o'lchamiga hali 6 bit qoldi. Nazariy jihatdan, ba'zi hollarda bu bir yil uchun etarli bo'lishi mumkin. Agar shunday bo'lmasa, boshqa bayt qo'shilishi ma'lumotlar maydonining hajmini 14 bitgacha oshiradi, bu 0-16383 oralig'ini beradi. Haqiqiy ilovalarda bu etarli. Hammasi bo'lib, biz kerakli ma'lumotlarni saqlash uchun zarur bo'lgan ma'lumotlar hajmini 5 baytgacha qisqartirdik. Agar bo'lmasa 4. Kamchilik avvalgi holatda bo'lgani kabi - agar siz qadoqlangan sanani saqlasangiz, unda konvertatsiya qilish usullari kerak bo'ladi. Lekin men buni shunday qilishni xohlayman: uni alohida maydonlarda saqlang va uni paketlangan shaklda seriyalashtiring. Bu erda foydalanish mantiqiy Externalizable:
// data is packed into 5 bytes:
//  3         2         1
// 10987654321098765432109876543210
// hhhhhmmmmmmssssssdddddMMMMyyyyyy yyyyyyyy
public void writeExternal(ObjectOutput out){
    int packed = 0;
    packed += ((int)hours) << 27;
    packed += ((int)minutes) << 21;
    packed += ((int)seconds) << 15;
    packed += ((int)day) << 10;
    packed += ((int)month) << 6;
    packed += (((int)year) >> 8) & 0x3F;
    out.writeInt(packed);
    out.writeByte((byte)year);
}

public void readExternal(ObjectInput in){
    int packed = in.readInt();
    year = in.readByte() & 0xFF;
    year += (packed & 0x3F) << 8;
    month = (packed >> 6) & 0x0F;
    day = (packed >> 10) & 0x1F;
    seconds = (packed >> 15) & 0x3F;
    minutes = (packed >> 21) & 0x3F;
    hours = (packed >> 27);
}
Aslida, hammasi shu. Seriyalashdan so'ng biz har bir sinfga qo'shimcha xarajatlarni, ikkita maydonni (6 o'rniga) va 5 bayt ma'lumotni olamiz. Bu allaqachon sezilarli darajada yaxshiroq. Keyingi qadoqlash ixtisoslashgan kutubxonalarga topshirilishi mumkin. Berilgan misol juda oddiy. Uning asosiy maqsadi ilg'or serializatsiyadan qanday foydalanish mumkinligini ko'rsatishdir. Seriyalashtirilgan ma'lumotlar hajmidagi mumkin bo'lgan daromad, mening fikrimcha, asosiy afzalliklardan uzoq bo'lsa-da. Asosiy afzallik, moslashuvchanlikdan tashqari... (keyingi bo'limga silliq o'ting ...) Manbaga havola: Seriyalashtirish
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION