JavaRush /Java Blogu /Random-AZ /Olduğu kimi seriallaşdırma. 1-ci hissə
articles
Səviyyə

Olduğu kimi seriallaşdırma. 1-ci hissə

Qrupda dərc edilmişdir
İlk baxışdan seriallaşdırma cüzi bir proses kimi görünür. Həqiqətən, daha sadə nə ola bilər? İnterfeys həyata keçirmək üçün sinif elan etdi java.io.Serializable- vəssalam. Sinfi problemsiz seriallaşdıra bilərsiniz. Olduğu kimi seriallaşdırma.  1-1 hissəTeorik olaraq bu doğrudur. Praktikada bir çox incəliklər var. Onlar performans, sıradan çıxarma, sinif təhlükəsizliyi ilə əlaqədardır. Və daha çox aspektləri ilə. Bu cür incəliklər müzakirə olunacaq. Bu məqaləni aşağıdakı hissələrə bölmək olar:
  • Mexanizmlərin incəlikləri
  • Niyə lazımdır?Externalizable
  • Performans
  • lakin digər tərəfdən
  • Məlumat Təhlükəsizliyi
  • Obyektin seriyalaşdırılmasıSingleton
Birinci hissəyə keçək -

Mexanizmlərin incəlikləri

İlk növbədə, sürətli bir sual. Obyekti seriyalı hala gətirməyin neçə yolu var? Təcrübə göstərir ki, tərtibatçıların 90% -dən çoxu bu suala təxminən eyni şəkildə cavab verir (yazıya qədər) - yalnız bir yol var. Bu arada onlardan ikisi var. Hər kəs ikincisini xatırlamır, onun xüsusiyyətləri haqqında anlaşılan bir şey söyləmək bir yana qalsın. Bəs bu üsullar nədir? Hər kəs birincisini xatırlayır. Bu artıq qeyd olunan tətbiqdir java.io.Serializablevə heç bir səy tələb etmir. İkinci üsul həm də interfeysin həyata keçirilməsidir, lakin fərqlidir: java.io.Externalizable. Fərqli olaraq java.io.Serializableo, həyata keçirilməli olan iki metodu ehtiva edir - writeExternal(ObjectOutput)readExternal(ObjectInput). Bu üsullar serializasiya/serializasiya məntiqini ehtiva edir. Şərh.Bundan sonra, mən bəzən standart olaraq tətbiqetmə ilə seriallaşdırmaya və genişləndirilmiş tətbiqə Serializableistinad edəcəyəm . ExternalizableBaşqaŞərh. readObjectMən qəsdən indi müəyyən və kimi standart serializasiya nəzarət variantlarına toxunmuram writeObject, çünki Məncə, bu üsullar bir qədər yanlışdır. Bu üsullar interfeysdə müəyyən edilməyib Serializablevə əslində məhdudiyyətlər ətrafında işləmək və standart seriallaşdırmanı çevik etmək üçün dəstəkdir. ExternalizableÇevikliyi təmin edən üsullar lap əvvəldən onların içində qurulur . Bir sual daha verək. dan istifadə edərək standart seriallaşdırma əslində necə işləyir java.io.Serializable? Və Reflection API vasitəsilə işləyir. Bunlar. sinif hər biri çıxış axınına yazılan sahələr dəsti kimi təhlil edilir. Hesab edirəm ki, bu əməliyyatın performans baxımından optimal olmadığı aydındır. Daha sonra dəqiq nə qədər olacağını öyrənəcəyik. Qeyd olunan iki seriallaşdırma metodu arasında başqa bir əsas fərq var. Məhz, sıradan çıxarma mexanizmində. İstifadə edildikdə, Serializableseriyasızlaşdırma belə baş verir: yaddaş bir obyekt üçün ayrılır, bundan sonra onun sahələri axın dəyərləri ilə doldurulur. Obyektin konstruktoru çağırılmır. Burada bu vəziyyəti ayrıca nəzərdən keçirməliyik. Yaxşı, sinifimiz seriallaşdırıla bilər. Bəs onun valideyni? Tamamilə isteğe bağlıdır! Üstəlik, əgər sizdən bir sinif miras alırsınızsa Object- valideyn mütləq seriallaşdırıla bilməz. Sahələr haqqında heç nə bilməsək də Object, onlar bizim öz valideyn siniflərimizdə mövcud ola bilər. Onlara nə olacaq? Onlar serializasiya axınına daxil olmayacaqlar. Serializasiyadan sonra hansı dəyərləri qəbul edəcəklər? Bu misala baxaq:
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;
        }
    }
}
O, şəffafdır - bizdə seriallaşdırıla bilməyən ana sinif və seriallaşdırıla bilən uşaq sinif var. Və belə olur:
Creating...
Parent::Constructor
Child::Constructor
Serializing...
Deserializing...
Parent::Constructor
c1.i=1
c1.field=5
Yəni sıradan çıxarma zamanı əsas NON-serializasiya edilə bilməyən sinifin parametrləri olmayan konstruktor deyilir . Və belə bir konstruktor yoxdursa, seriyadan çıxarma zamanı xəta baş verəcəkdir. Seriyadan çıxardığımız uşaq obyektin konstruktoru yuxarıda deyildiyi kimi çağırılmır. Standart mexanizmlər istifadə edildikdə belə davranır Serializable. Onu istifadə edərkən Externalizablevəziyyət fərqlidir. Əvvəlcə parametrləri olmayan konstruktor çağırılır, sonra isə bütün verilənləri oxuyan yaradılmış obyektdə readExternal metodu çağırılır. Buna görə də, Externalizable interfeysini həyata keçirən istənilən sinif parametrləri olmayan ictimai konstruktora malik olmalıdır! Üstəlik, belə bir sinfin bütün nəsilləri də interfeysi həyata keçirmək üçün nəzərdə tutulacağından Externalizable, onların parametrsiz konstruktoru da olmalıdır! Gəlin daha da irəli gedək. kimi bir sahə dəyişdiricisi var transient. Bu o deməkdir ki, bu sahə seriallaşdırılmamalıdır. Ancaq özünüz başa düşdüyünüz kimi, bu təlimat yalnız standart seriallaşdırma mexanizminə təsir göstərir. İstifadə edildikdə, Externalizableheç kim bu sahəni seriallaşdırmaqla yanaşı, onu çıxarmaq üçün də narahat etmir. Sahə keçici elan edilirsə, o zaman obyekt seriyadan çıxarıldıqda, standart dəyəri alır. Başqa bir incə məqam. Standart seriallaşdırma ilə dəyişdiricisi olan sahələr staticseriallaşdırılmır. Müvafiq olaraq, seriyadan çıxarıldıqdan sonra bu sahə dəyərini dəyişmir. Əlbəttə ki, tətbiq zamanı Externalizableheç kim bu sahəni seriallaşdırmaq və seriyadan çıxarmaqdan narahat deyil, amma bunu etməməyi çox tövsiyə edirəm, çünki bu incə səhvlərə səbəb ola bilər. Dəyişdiricisi olan sahələr finaladi sahələr kimi seriallaşdırılır. Bir istisna ilə - Externalizable istifadə edərkən onlar seriyadan çıxarıla bilməz. Çünki final-поляonlar konstruktorda inisiallaşdırılmalıdır və bundan sonra readExternal-da bu sahənin dəyərini dəyişmək mümkün olmayacaq. Müvafiq olaraq, -sahəsi olan bir obyekti seriallaşdırmaq lazımdırsa final, yalnız standart seriallaşdırmadan istifadə etməli olacaqsınız. Çoxlarının bilmədiyi başqa bir məqam. Standart serializasiya sinifdə sahələrin elan olunma sırasını nəzərə alır. Hər halda, əvvəlki versiyalarda belə idi; Oracle tətbiqinin JVM 1.6 versiyasında artıq sıra vacib deyil, sahənin növü və adı vacibdir. Sahələrin ümumiyyətlə eyni qala biləcəyinə baxmayaraq, metodların tərkibinin standart mexanizmə təsir göstərmə ehtimalı yüksəkdir. Bunun qarşısını almaq üçün aşağıdakı mexanizm mövcuddur. İnterfeys həyata keçirən hər bir sinifə Serializabletərtib mərhələsində daha bir sahə əlavə olunur -private static final long serialVersionUID. Bu sahədə seriallaşdırılmış sinfin unikal versiya identifikatoru var. O, sinfin məzmununa - sahələrə, onların bəyan etmə sırasına, metodlarına, bəyan etmə sırasına əsasən hesablanır. Müvafiq olaraq, sinifdə hər hansı bir dəyişikliklə bu sahə öz dəyərini dəyişəcəkdir. Sinif seriallaşdırıldıqda bu sahə axına yazılır. Yeri gəlmişkən, bu, bəlkə də staticbir sahənin seriallaşdırıldığı zaman mənə məlum olan yeganə haldır. Seriyadan çıxarma zamanı bu sahənin dəyəri virtual maşındakı siniflə müqayisə edilir. Dəyərlər uyğun gəlmirsə, belə bir istisna atılır:
java.io.InvalidClassException: test.ser2.ChildExt;
    local class incompatible: stream classdesc serialVersionUID = 8218484765288926197,
                                   local class serialVersionUID = 1465687698753363969
Bununla belə, bu çeki aldatmağın bir yolu var. Bu, sinif sahələri dəsti və onların sırası artıq müəyyən edildikdə faydalı ola bilər, lakin sinif metodları dəyişə bilər. Bu halda serializasiya risk altında deyil, lakin standart mexanizm dəyişdirilmiş sinfin bayt kodundan istifadə edərək verilənlərin seriyadan çıxarılmasına imkan verməyəcək. Amma dediyim kimi, onu aldatmaq olar. Yəni, sinifdəki sahəni əl ilə təyin edin private static final long serialVersionUID. Prinsipcə, bu sahənin dəyəri tamamilə hər şey ola bilər. Bəzi insanlar onu kodun dəyişdirildiyi tarixə bərabər tutmağa üstünlük verirlər. Bəziləri hətta 1 litr istifadə edirlər. Standart dəyəri (daxili olaraq hesablanan) əldə etmək üçün SDK-ya daxil olan serialver yardım proqramından istifadə edə bilərsiniz. Bu şəkildə müəyyən edildikdən sonra sahənin dəyəri sabitlənəcək, buna görə də seriyadan çıxarmağa həmişə icazə veriləcəkdir. Üstəlik, 5.0 versiyasında sənədlərdə təxminən aşağıdakılar ortaya çıxdı: bütün seriallaşdırıla bilən siniflərin bu sahəni açıq şəkildə elan etməsi tövsiyə olunur, çünki standart hesablama sinif strukturunun təfərrüatlarına çox həssasdır, kompilyatorun tətbiqindən asılı olaraq dəyişə bilər, və beləliklə InvalidClassException, gözlənilməz nəticələrə səbəb olur. Bu sahəni kimi elan etmək daha yaxşıdır private, çünki o, yalnız elan olunduğu sinfə aiddir. Dəyişdirici spesifikasiyada göstərilməsə də. İndi bu aspekti nəzərdən keçirək. Deyək ki, bu sinif quruluşumuz var:
public class A{
    public int iPublic;
    protected int iProtected;
    int iPackage;
    private int iPrivate;
}

public class B extends A implements Serializable{}
Başqa sözlə, seriallaşdırıla bilməyən valideyndən miras qalmış bir sinifimiz var. Bu sinfi seriallaşdırmaq mümkündürmü və bunun üçün nə lazımdır? Ana sinifin dəyişənləri ilə nə olacaq? Cavab budur. Bəli, Bsiz bir sinif nümunəsini seriallaşdıra bilərsiniz. Bunun üçün nə lazımdır? Lakin sinifdə Aparametrləri olmayan konstruktor publicvə ya protected. Sonra sıradan çıxarma zamanı bütün sinif dəyişənləri Abu konstruktordan istifadə etməklə inisiallaşdırılacaq. Sinif dəyişənləri Bseriallaşdırılmış məlumat axınının dəyərləri ilə işə salınacaq. BTeorik olaraq, bir sinifdə əvvəlində haqqında danışdığım üsulları müəyyən etmək mümkündür - readObjectwriteObject, - əvvəlində sinif dəyişənlərinin seriyalılaşdırılması (de-) Bvasitəsilə həyata keçirilməli in.defaultReadObject/out.defaultWriteObjectvə sonra mövcud dəyişənlərin (de-) seriyalılaşdırılması sinifdən A(bizim vəziyyətimizdə bunlar iPublic, iProtectediPackage, Bilə eyni paketdədirsə A). Lakin, fikrimcə, bunun üçün uzadılmış serializasiyadan istifadə etmək daha yaxşıdır. Toxunmaq istədiyim növbəti məqam çoxlu obyektlərin seriallaşdırılmasıdır. Deyək ki, aşağıdakı sinif quruluşumuz var:
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;}
}
Olduğu kimi seriallaşdırma.  1-2 hissəSinfin nümunəsini seriallaşdırsanız nə olar A? O, sinfin bir nümunəsi boyunca sürüklənəcək , bu da öz növbəsində , hamısının başladığı eyni nümunəyə istinadı olan Bbir nümunə boyunca sürüklənəcək . Şiddətli dairə və sonsuz rekursiya? Xoşbəxtlikdən, yox. Aşağıdakı test koduna baxaq: CA
// 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 nə edirik? Biz siniflərin nümunəsini yaradırıq AB, Conlara bir-birinə keçidlər veririk və sonra onların hər birini seriallaşdırırıq. Sonra onları sıradan çıxarırıq və bir sıra yoxlamalar aparırıq. Nəticədə nə olacaq:
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
Beləliklə, bu testdən nə öyrənə bilərsiniz? Birinci. Seriyadan çıxarıldıqdan sonra obyekt istinadları ondan əvvəlki istinadlardan fərqlidir. Başqa sözlə, serializasiya/deserializasiya zamanı obyekt kopyalanıb. Bu üsul bəzən obyektləri klonlamaq üçün istifadə olunur. İkinci nəticə daha əhəmiyyətlidir. Çarpaz istinadları olan çoxlu obyektlərin serializasiyası/serializasiyası zamanı həmin istinadlar seriyadan çıxarıldıqdan sonra etibarlı qalır. Başqa sözlə, serializasiyadan əvvəl onlar bir obyektə işarə edirdilərsə, serializasiyadan sonra onlar da bir obyektə işarə edəcəklər. Bunu təsdiqləmək üçün başqa bir kiçik 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));
Sinif obyektinin Bsinif obyektinə istinadı var C. Seriallaşdırıldıqda, bo, sinif nümunəsi ilə birlikdə seriallaşdırılır С, bundan sonra eyni c nümunəsi üç dəfə seriallaşdırılır. Seriyadan çıxarıldıqdan sonra nə baş verir?
b1.getC()==c1: true
c1==c2: true
c1==c3: true
Gördüyünüz kimi, sıradan çıxarılan dörd obyektin hamısı əslində bir obyekti təmsil edir - ona istinadlar bərabərdir. Seriallaşmadan əvvəl olduğu kimi. Başqa bir maraqlı məqam - biz eyni vaxtda həyata keçirsək nə olacaq ExternalizableSerializable? Bu sualda olduğu kimi - fil və balina - kim kimə qalib gələcək? qalib gələcək Externalizable. Serializasiya mexanizmi əvvəlcə onun mövcudluğunu yoxlayır və yalnız bundan sonra onun mövcudluğunu yoxlayır.Belə Serializableki, tətbiq edən B sinfi SerializableA sinfindən miras alırsa Externalizable, B sinifinin sahələri seriallaşdırılmayacaq. Son nöqtə mirasdır. -i həyata keçirən sinifdən miras alındıqda Serializable, heç bir əlavə hərəkətə ehtiyac yoxdur. Serializasiya uşaq sinifinə də şamil ediləcək. -ı həyata keçirən sinifdən miras alarkən Externalizable, siz ana sinfin readExternal və writeExternal metodlarını ləğv etməlisiniz. Əks halda, uşaq sinifinin sahələri seriallaşdırılmayacaq. Bu halda, siz ana metodları çağırmağı unutmayın, əks halda ana sahələr seriallaşdırılmayacaq. * * * Detalları yəqin ki, bitirdik. Bununla belə, toxunmadığımız bir məsələ var, qlobal xarakter daşıyır. Məhz -

Nə üçün sizə Externalizable lazımdır?

Niyə ümumiyyətlə təkmil seriallaşdırmaya ehtiyacımız var? Cavab sadədir. Birincisi, daha çox çeviklik verir. İkincisi, seriallaşdırılmış məlumatların həcmi baxımından çox vaxt əhəmiyyətli qazanclar təmin edə bilər. Üçüncüsü, aşağıda danışacağımız performans kimi bir cəhət var . Çevikliklə hər şey aydın görünür. Həqiqətən, biz seriallaşdırma və sıradan çıxarma proseslərini istədiyimiz kimi idarə edə bilirik ki, bu da bizi sinifdəki hər hansı bir dəyişiklikdən müstəqil edir (yuxarıda dediyim kimi, sinifdəki dəyişikliklər seriyasızlaşdırmaya böyük təsir göstərə bilər). Buna görə də həcmdə qazanc haqqında bir neçə söz demək istəyirəm. Deyək ki, bizdə aşağıdakı sinif var:
public class DateAndTime{

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

}
Qalanları əhəmiyyətsizdir. Sahələr int tipindən hazırlana bilər, lakin bu, yalnız nümunənin təsirini artıracaq. Baxmayaraq ki, reallıqda sahələr intperformans səbəbləri ilə yazıla bilər. Hər halda məsələ aydındır. Sinif tarix və vaxtı təmsil edir. Bizim üçün ilk növbədə seriallaşma baxımından maraqlıdır. Ola bilsin ki, ediləcək ən asan şey sadə vaxt möhürü saxlamaqdır. Uzun tipdir, yəni. seriallaşdırılmış zaman 8 bayt alacaqdı. Bundan əlavə, bu yanaşma komponentləri bir dəyərə və geriyə çevirmək üsullarını tələb edir, yəni. - məhsuldarlığın itirilməsi. Bu yanaşmanın üstünlüyü 64 bitə sığa bilən tamamilə çılğın bir tarixdir. Bu, çox vaxt reallıqda lazım olmayan böyük bir təhlükəsizlik marjasıdır. Yuxarıda verilmiş sinif 2 + 5*1 = 7 bayt alacaq. Üstəlik sinif və 6 sahə üçün yerüstü xərclər. Bu məlumatları sıxışdırmağın hər hansı bir yolu varmı? Əminliklə. Saniyələr və dəqiqələr 0-59 aralığındadır, yəni. onları təmsil etmək üçün 8 əvəzinə 6 bit kifayətdir. Saatlar – 0-23 (5 bit), günlər – 0-30 (5 bit), aylar – 0-11 (4 bit). Cəmi, il nəzərə alınmadan hər şey - 26 bit. int ölçüsünə hələ 6 bit qalıb. Teorik olaraq, bəzi hallarda bu, bir il üçün kifayət edə bilər. Əgər belə deyilsə, başqa baytın əlavə edilməsi məlumat sahəsinin ölçüsünü 14 bitə qədər artırır ki, bu da 0-16383 diapazonunu verir. Bu, real tətbiqlərdə kifayət qədərdir. Ümumilikdə, biz lazımi məlumatları saxlamaq üçün tələb olunan məlumatların ölçüsünü 5 bayta endirmişik. Əgər 4-ə qədər deyilsə. Dezavantajı əvvəlki vəziyyətdə olduğu kimidir - əgər tarixi qablaşdırılaraq saxlayırsınızsa, onda dönüşüm üsulları lazımdır. Amma mən bunu belə etmək istəyirəm: onu ayrı-ayrı sahələrdə saxlayın və paketlənmiş formada seriallaşdırın. Burada istifadə etmək məntiqlidir 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);
}
Əslində, hamısı budur. Serializasiyadan sonra biz hər sinifə əlavə yük, iki sahə (6 əvəzinə) və 5 bayt məlumat alırıq. Hansı ki, artıq əhəmiyyətli dərəcədə yaxşıdır. Əlavə qablaşdırma ixtisaslaşdırılmış kitabxanalara buraxıla bilər. Verilən nümunə çox sadədir. Onun əsas məqsədi təkmil seriallaşdırmanın necə istifadə oluna biləcəyini göstərməkdir. Seriallaşdırılmış məlumatların həcmində mümkün qazanc, fikrimcə, əsas üstünlükdən uzaq olsa da. Əsas üstünlük, çeviklikdən əlavə... (rəvan şəkildə növbəti hissəyə keçin...) Mənbəyə keçid: Olduğu kimi seriallaşdırma
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION