JavaRush /جاوا بلاگ /Random-SD /سيريلائيزيشن جيئن ته آهي. حصو 1
articles
سطح

سيريلائيزيشن جيئن ته آهي. حصو 1

گروپ ۾ شايع ٿيل
پهرين نظر ۾، سيريلائيزيشن هڪ معمولي عمل وانگر لڳي ٿو. واقعي، ڇا آسان ٿي سگهي ٿو؟ انٽرفيس کي لاڳو ڪرڻ لاءِ ڪلاس جو اعلان ڪيو java.io.Serializable- ۽ اهو ئي آهي. توهان بغير ڪنهن مسئلن جي ڪلاس کي ترتيب ڏئي سگهو ٿا. سيريلائيزيشن جيئن ته آهي.  حصو 1 - 1نظرياتي طور تي، اهو سچ آهي. عملي طور تي، اتي تمام گهڻو subtleties آهن. اهي ڪارڪردگي سان لاڳاپيل آهن، ترتيب ڏيڻ، طبقي جي حفاظت سان. ۽ ڪيترن ئي حصن سان. اهڙي subtleties ڳالهه ٻولهه ڪئي ويندي. هن مضمون کي هيٺين حصن ۾ ورهائي سگهجي ٿو:
  • ميڪانيزم جي ذيلي ذخيري
  • ان جي ضرورت ڇو آهي؟Externalizable
  • ڪارڪردگي
  • پر ٻئي طرف
  • ڊيٽا سيڪيورٽي
  • آبجیکٹ سيريلائيزيشنSingleton
اچو ته پهرين حصي ڏانهن وڃو -

ميڪانيزم جي ذيلي ذخيري

سڀ کان پهريان، هڪ تڪڙو سوال. ڪيترا ئي طريقا آھن ھڪڙي اعتراض کي ترتيب ڏيڻ لاءِ؟ مشق ڏيکاري ٿو ته ڊولپرز جي 90 سيڪڙو کان وڌيڪ هن سوال جو جواب تقريبا ساڳئي طريقي سان (لفظن تائين) - صرف هڪ طريقو آهي. ان دوران، انهن مان ٻه آهن. هر ڪنهن کي ياد ناهي ته ٻئي کي، اڪيلو ڇڏي ڏيو ڪجھ به ان جي خاصيتن جي باري ۾ سمجھڻ وارو. پوء اهي طريقا ڇا آهن؟ هر ڪو پهريون ياد رکندو آهي. اهو اڳ ۾ ئي ذڪر ڪيل عمل آهي java.io.Serializable۽ ڪنهن به ڪوشش جي ضرورت ناهي. ٻيو طريقو پڻ هڪ انٽرفيس تي عمل ڪرڻ آهي، پر هڪ مختلف آهي: java.io.Externalizable. ان جي برعڪس java.io.Serializable، ان ۾ ٻه طريقا شامل آھن جن تي عمل ڪرڻ جي ضرورت آھي - writeExternal(ObjectOutput)۽ readExternal(ObjectInput). انهن طريقن ۾ سيريلائيزيشن/ڊيسيريلائيزيشن منطق شامل آهي. تبصرو.Serializableهيٺ ڏنل ۾ ، مان ڪڏهن ڪڏهن حوالو ڏيندس سيريلائيزيشن سان عمل درآمد کي معياري طور تي، ۽ عملدرآمد Externalizableجي طور تي وڌايو ويو. ٻيوتبصرو. مان عمدي طور تي ھاڻي ھاڻي نه ھاڻي ھاڻي ھاڻي ھاڻي معياري سيريلائيزيشن ڪنٽرول آپشنز جي وضاحت ڪرڻ readObject۽ writeObject، ڇاڪاڻ ته منهنجو خيال آهي ته اهي طريقا ڪجهه غلط آهن. اهي طريقا انٽرفيس ۾ بيان نه ڪيا ويا آهن Serializable۽ حقيقت ۾ آهن، حدن جي چوڌاري ڪم ڪرڻ ۽ معياري سيريلائيزيشن کي لچڪدار بڻائڻ لاءِ. Externalizableاهي طريقا جيڪي لچڪ فراهم ڪن ٿا انهن ۾ شروع کان ئي ٺهيل آهن . اچو ته هڪ ٻيو سوال پڇون. معياري سيريلائيزيشن اصل ۾ ڪيئن ڪم ڪندو آهي، استعمال ڪندي java.io.Serializable؟ ۽ اهو ڪم ڪري ٿو Reflection API ذريعي. اهي. ڪلاس کي فيلڊ جي سيٽ جي طور تي پارس ڪيو ويو آهي، جن مان هر هڪ آئوٽ اسٽريم ڏانهن لکيل آهي. مان سمجهان ٿو ته اهو واضح آهي ته هي آپريشن ڪارڪردگي جي لحاظ کان بهتر ناهي. اسان بعد ۾ معلوم ڪنداسين ته ڪيترو صحيح آهي. ذڪر ڪيل ٻن سيريلائيزيشن طريقن جي وچ ۾ هڪ ٻيو وڏو فرق آهي. يعني، deserialization ميڪانيزم ۾. جڏهن استعمال ڪيو وڃي، Serializabledeserialization هن طرح ٿئي ٿي: ياداشت هڪ اعتراض لاء مختص ڪئي وئي آهي، جنهن کان پوء ان جا شعبا نديء جي قدرن سان ڀريو وڃي ٿو. اعتراض جي تعمير ڪندڙ نه سڏيو ويندو آهي. هتي اسان کي الڳ الڳ هن صورتحال تي غور ڪرڻ جي ضرورت آهي. ٺيڪ آهي، اسان جو ڪلاس سيريل آهي. ۽ سندس والدين؟ مڪمل طور تي اختياري! ان کان علاوه، جيڪڏهن توهان هڪ طبقي مان ورثي ۾ آهيو Object- والدين يقيني طور تي سيريلائيز نه آهي. ۽ جيتوڻيڪ Objectاسان فيلڊن بابت ڪجھ به نٿا ڄاڻون، اهي شايد اسان جي پنهنجي والدين طبقن ۾ موجود هجن. انهن جو ڇا ٿيندو؟ اهي سيريلائيزيشن جي وهڪري ۾ نه ايندا. اهي ڪهڙيون قيمتون deserialization تي کڻندا؟ اچو ته هن مثال کي ڏسو:
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;
        }
    }
}
اهو شفاف آهي - اسان وٽ هڪ غير سيريلائيزبل والدين ڪلاس ۽ هڪ سيريلائيزبل چائلڊ ڪلاس آهي. ۽ اهو ئي ٿئي ٿو:
Creating...
Parent::Constructor
Child::Constructor
Serializing...
Deserializing...
Parent::Constructor
c1.i=1
c1.field=5
اھو آھي، deserialization جي دوران، ٺاھيندڙ کي سڏيو ويندو آھي پيرن نان-سيريلائيبل ڪلاس جي پيرا ميٽرن جي بغير . ۽ جيڪڏهن ڪو اهڙو تعمير ڪندڙ نه آهي، هڪ غلطي ٿيندي ڊيسيريلائيزيشن دوران. چائلڊ اعتراض جو ٺاھيندڙ، جنھن کي اسين ختم ڪري رھيا آھيون، ان کي نه سڏيو ويندو آھي، جيئن مٿي چيو ويو آھي. هي آهي ڪيئن معياري ميڪانيزم استعمال ڪيو جڏهن استعمال ڪيو وڃي Serializable. جڏهن ان کي استعمال ڪندي، Externalizableصورتحال مختلف آهي. پھريائين، ٺاھيندڙ کي پيراميٽر کان سواءِ سڏيو ويندو آھي، ۽ پوءِ ٺاھيل اعتراض تي readExternal طريقو سڏيو ويندو آھي، جيڪو اصل ۾ ان جي سموري ڊيٽا پڙھندو آھي. تنهن ڪري، ڪنهن به طبقي کي لاڳو ڪندڙ Externalizable انٽرفيس کي لازمي طور تي پبلڪ ڪنسٽرڪٽر هجڻ گهرجي، بغير پيٽرولر جي! ان کان علاوه، جيئن ته اهڙي طبقي جي سڀني اولادن کي به انٽرفيس کي لاڳو ڪرڻ تي غور ڪيو ويندو Externalizable، انهن وٽ پڻ هڪ غير معياري تعمير ڪندڙ هجڻ گهرجي! اچو ته اڳتي وڌون. اتي ھڪڙو فيلڊ موڊيفائر آھي جيئن transient. مطلب ته هن فيلڊ کي سيريل نه ڪيو وڃي. بهرحال، جيئن توهان پاڻ کي سمجھيو، هي هدايت صرف معياري سيريلائيزيشن ميڪانيزم کي متاثر ڪري ٿو. جڏهن استعمال ڪيو وڃي، Externalizableڪو به هن فيلڊ کي سيريل ڪرڻ جي زحمت نه ڪندو آهي، انهي سان گڏ ان کي ختم ڪرڻ. جيڪڏهن هڪ فيلڊ کي عارضي قرار ڏنو ويو آهي، پوء جڏهن اعتراض ختم ڪيو ويندو آهي، اهو ڊفالٽ قيمت تي وٺندو آهي. هڪ ٻيو نهايت نازڪ نقطو. معياري سيريلائيزيشن سان، فيلڊ جيڪي تبديل ڪندڙ آهن staticسيريلائيز نه آهن. ان مطابق، deserialization کان پوء هي ميدان ان جي قيمت تبديل نه ڪندو آھي. يقينن، عمل جي دوران، Externalizableڪو به هن فيلڊ کي سيريل ڪرڻ ۽ ختم ڪرڻ جي زحمت نه ڪندو آهي، پر مان سفارش ڪريان ٿو ته اهو نه ڪيو وڃي، ڇاڪاڻ ته ان سان ننڍيون غلطيون ٿي سگهن ٿيون. هڪ ترميمي سان فيلڊ finalسيريل ٿيل آهن جيئن باقاعده آهن. هڪ استثنا سان - انهن کي ختم نه ٿي ڪري سگھجي جڏهن Externalizable استعمال ڪندي. ڇاڪاڻ ته final-поляانهن کي تعمير ڪندڙ ۾ شروع ٿيڻ گهرجي، ۽ ان کان پوء هن فيلڊ جي قيمت کي readExternal ۾ تبديل ڪرڻ ناممڪن ٿي ويندو. ان جي مطابق، جيڪڏهن توهان کي ڪنهن شئي کي سيريل ڪرڻ جي ضرورت آهي جيڪا finalهڪ فيلڊ آهي، توهان کي صرف معياري سيريلائيزيشن استعمال ڪرڻو پوندو. ٻيو نقطو جيڪو ڪيترن ئي ماڻهن کي خبر ناهي. معياري سيريلائيزيشن انهي ترتيب کي حساب ۾ رکي ٿو جنهن ۾ فيلڊ کي ڪلاس ۾ اعلان ڪيو ويو آهي. ڪنهن به صورت ۾، اهو معاملو اڳئين نسخن ۾ هو؛ Oracle عمل درآمد جي JVM نسخو 1.6 ۾، آرڊر هاڻي اهم ناهي، فيلڊ جو قسم ۽ نالو اهم آهن. طريقن جي جوڙجڪ معياري ميڪانيزم کي متاثر ڪرڻ جو تمام گهڻو امڪان آهي، ان حقيقت جي باوجود ته فيلڊ عام طور تي ساڳيا رهي سگهن ٿيون. ھن کان بچڻ لاء، ھيٺ ڏنل ميکانيزم آھي. هر ڪلاس ۾ جيڪو انٽرفيس کي لاڳو ڪري ٿو Serializable، هڪ وڌيڪ فيلڊ شامل ڪيو ويو آهي تاليف واري مرحلي ۾ -private static final long serialVersionUID. ھن فيلڊ ۾ سيريل ٿيل ڪلاس جي منفرد ورزن جي سڃاڻپ ڪندڙ آھي. اهو ڪلاس جي مواد جي بنياد تي حساب ڪيو ويو آهي - فيلڊ، انهن جي اعلان جي ترتيب، طريقن، انهن جي اعلان جي ترتيب. ان مطابق، ڪلاس ۾ ڪنهن به تبديلي سان، هي فيلڊ ان جي قيمت تبديل ڪندو. هي فيلڊ اسٽريم ڏانهن لکيو ويندو آهي جڏهن ڪلاس سيريل ڪيو ويندو آهي. رستي ۾، اهو شايد واحد ڪيس آهي جيڪو مون کي معلوم ٿئي ٿو جڏهن staticهڪ فيلڊ سيريل ڪيو ويو آهي. deserialization دوران، هن فيلڊ جي قيمت ورچوئل مشين ۾ ڪلاس جي مقابلي ۾ آهي. جيڪڏهن قدر نه ملندا آهن، هڪ استثنا هن طرح اڇلايو ويندو آهي:
java.io.InvalidClassException: test.ser2.ChildExt;
    local class incompatible: stream classdesc serialVersionUID = 8218484765288926197,
                                   local class serialVersionUID = 1465687698753363969
تنهن هوندي به، هڪ طريقو آهي، جيڪڏهن نه بائي پاس، پوء هن چيڪ کي ٺڳيو. اهو ڪارائتو ٿي سگهي ٿو جيڪڏهن طبقاتي شعبن جو سيٽ ۽ انهن جي ترتيب اڳ ۾ ئي وضاحت ڪئي وئي آهي، پر طبقاتي طريقا تبديل ٿي سگهن ٿا. انهي صورت ۾، سيريلائيزيشن خطري ۾ نه آهي، پر معياري ميکانيزم ڊيٽا کي تبديل ٿيل طبقي جي بائيٽ ڪوڊ استعمال ڪندي ڊيٽا کي ختم ڪرڻ جي اجازت نه ڏيندو. پر، جيئن مون چيو، هن کي ٺڳي سگهجي ٿو. يعني، دستي طور ڪلاس ۾ فيلڊ جي وضاحت ڪريو private static final long serialVersionUID. اصول ۾، هن ميدان جي قيمت بلڪل ڪجهه ٿي سگهي ٿو. ڪجهه ماڻهو انهي کي ترتيب ڏيڻ کي ترجيح ڏيندا آهن انهي جي برابر تاريخ جي ڪوڊ ۾ ترميم ڪئي وئي هئي. ڪجھ به 1L استعمال ڪن ٿا. معياري قدر حاصل ڪرڻ لاءِ (جيڪو اندروني طور تي ڳڻيو وڃي ٿو)، توھان استعمال ڪري سگھو ٿا سيريلور يوٽيلٽي SDK ۾ شامل. هڪ دفعو هن طريقي سان بيان ڪيو ويو آهي، فيلڊ جي قيمت مقرر ڪئي ويندي، تنهنڪري ڊيسيريلائيزيشن هميشه اجازت ڏني ويندي. ان کان علاوه، ورزن 5.0 ۾، تقريبن ھيٺ ڏنل دستاويزن ۾ ظاهر ٿيو: اھو انتهائي صلاح ڏني وئي آھي ته سڀئي سيريلائيبل ڪلاس ھن فيلڊ کي واضح طور تي بيان ڪن، ڇاڪاڻ⁠تہ ڊفالٽ حساب ڪتاب طبقي جي جوڙجڪ جي تفصيل سان تمام حساس آھي، جيڪو مختلف ٿي سگھي ٿو مرتب ڪرڻ واري عمل جي لحاظ کان، ۽ اهڙيءَ طرح اڻڄاتل InvalidClassExceptionنتيجن جو سبب بڻجن ٿا. deserialization. اهو بهتر آهي ته هن فيلڊ کي اعلان ڪيو وڃي private، ڇاڪاڻ ته اهو صرف ان طبقي ڏانهن اشارو ڪري ٿو جنهن ۾ اهو اعلان ڪيو ويو آهي. جيتوڻيڪ modifier جي وضاحت ۾ بيان نه ڪيو ويو آهي. اچو ته هاڻي هن نقطي تي غور ڪريون. اچو ته چئو ته اسان وٽ هن طبقي جي جوڙجڪ آهي:
public class A{
    public int iPublic;
    protected int iProtected;
    int iPackage;
    private int iPrivate;
}

public class B extends A implements Serializable{}
ٻين لفظن ۾، اسان وٽ ھڪڙو طبقو آھي جيڪو ھڪڙي غير سيريلائيزبل والدين کان وراثت ۾ آھي. ڇا اهو ممڪن آهي ته هن طبقي کي ترتيب ڏيو، ۽ ان لاء ڇا گهربل آهي؟ والدين طبقي جي متغيرن جو ڇا ٿيندو؟ جواب هي آهي. ها، Bتوهان ڪلاس جي هڪ مثال کي ترتيب ڏئي سگهو ٿا. ان لاءِ ڪهڙي ضرورت آهي؟ پر ڪلاس کي ضرورت آھي Aھڪڙو ٺاھيندڙ بغير پيٽرولر جي، publicيا protected. ان کان پوء، deserialization دوران، سڀني طبقي متغيرن کي Aهن تعمير ڪندڙ استعمال ڪندي شروع ڪيو ويندو. ڪلاس متغيرن کي Bسيريل ٿيل ڊيٽا اسٽريم مان ويلن سان شروع ڪيو ويندو. نظرياتي طور تي، اهو ممڪن آهي ته ڪنهن طبقي ۾ Bاهي طريقا بيان ڪيا وڃن جن جي باري ۾ مون شروعات ۾ ڳالهه ڪئي هئي - readObject۽ writeObject، - جنهن جي شروعات ۾ (de-) ڪلاس متغيرن جي سيريلائيزيشن Bذريعي in.defaultReadObject/out.defaultWriteObject، ۽ پوءِ (de-) دستياب متغيرن جي سيريلائيزيشن. طبقن مان A(اسان جي حالت ۾ اهي آهن iPublic، iProtected۽ iPackage، جيڪڏهن Bاهو ساڳيو پيڪيج ۾ آهي A). بهرحال، منهنجي خيال ۾، اهو بهتر آهي ته هن لاء وڌايو سيريلائيزيشن استعمال ڪريو. اڳيون نقطو جنهن تي مان رابطو ڪرڻ چاهيان ٿو ڪيترن ئي شين جي سيريلائيزيشن. اچو ته چئون ته اسان وٽ هيٺين طبقي جي جوڙجڪ آهي:
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;}
}
سيريلائيزيشن جيئن ته آهي.  حصو 1 - 2ڇا ٿيندو جيڪڏھن توھان ڪلاس جي ھڪڙي مثال کي ترتيب ڏيو A؟ اهو ڪلاس جي هڪ مثال سان گڏ ڇڪيندو B، جيڪو، موڙ ۾، هڪ مثال سان گڏ ڇڪيندو Cجنهن ۾ مثال جو حوالو هوندو A، اهو ساڳيو آهي جنهن سان اهو سڀ شروع ٿيو. شيطاني دائرو ۽ لامحدود تکرار؟ خوشقسمتيء سان، نه. اچو ته هيٺ ڏنل ٽيسٽ ڪوڊ ڏسو:
// 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));
اسان ڇا ڪري رهيا آهيون؟ اسان طبقن جو هڪ مثال ٺاهيو A، B۽ C، انهن کي هڪ ٻئي سان ڳنڍيو، ۽ پوء انهن مان هر هڪ کي ترتيب ڏيو. ان کان پوء اسان انهن کي واپس هٽايو ۽ چيڪن جو هڪ سلسلو هلائيندا آهيون. نتيجي ۾ ڇا ٿيندو:
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
پوء توهان هن امتحان مان ڇا سکي سگهو ٿا؟ پهريون. ڊيسيريلائيزيشن کان پوءِ اعتراض جا حوالا ان کان اڳ ڏنل حوالن کان مختلف آهن. ٻين لفظن ۾، سيريلائيزيشن/ڊيسيريلائيزيشن دوران اعتراض نقل ڪيو ويو. اهو طريقو ڪڏهن ڪڏهن شيون کلون ڪرڻ لاء استعمال ڪيو ويندو آهي. ٻيو نتيجو وڌيڪ اهم آهي. جڏهن ڪيترن ئي شين کي سيريلائيز/ڊيسيريلائيز ڪيو وڃي جن ۾ ڪراس ريفرنس هجي، اهي حوالا ڊيسيريلائيزيشن کان پوءِ صحيح رهندا. ٻين لفظن ۾، جيڪڏهن سيريلائيزيشن کان اڳ انهن هڪ اعتراض ڏانهن اشارو ڪيو، ته پوء سيريلائيزيشن کان پوء اهي به هڪ اعتراض ڏانهن اشارو ڪندا. هن جي تصديق ڪرڻ لاء هڪ ٻيو ننڍڙو امتحان:
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));
هڪ طبقاتي اعتراض جو Bحوالو آهي طبقاتي اعتراض ڏانهن C. جڏهن سيريل ڪيو ويندو آهي، bاهو ڪلاس جي هڪ مثال سان گڏ سيريل ڪيو ويندو آهي С، جنهن کان پوء سي جي ساڳئي مثال کي ٽي ڀيرا سيريل ڪيو ويندو آهي. Deserialization کان پوء ڇا ٿيندو؟
b1.getC()==c1: true
c1==c2: true
c1==c3: true
جئين توهان ڏسي سگهو ٿا، سڀئي چار بي ترتيب ڪيل شيون اصل ۾ هڪ اعتراض جي نمائندگي ڪن ٿا - ان جا حوالا برابر آهن. بلڪل ائين جيئن سيريل ٿيڻ کان اڳ هو. هڪ ٻيو دلچسپ نقطو - ڇا ٿيندو جيڪڏهن اسان هڪ ئي وقت تي عمل ڪيو Externalizable۽ Serializable؟ جيئن ان سوال ۾ - هاٿي بمقابله وهيل - ڪير ڪنهن کي شڪست ڏيندو؟ غالب ڪندو Externalizable. سيريلائيزيشن ميڪانيزم پهريان ان جي موجودگي جي جانچ ڪري ٿو، ۽ صرف ان کان پوء ان جي موجودگي لاء، Serializableتنهنڪري جيڪڏهن ڪلاس B، جيڪو لاڳو ڪري ٿو Serializable، ڪلاس A مان ورثي ۾ اچي ٿو، جيڪو لاڳو ڪري ٿو Externalizable، ڪلاس B جي شعبن کي سيريل نه ڪيو ويندو. آخري نقطو وراثت آهي. جڏهن هڪ طبقي مان ورثي ۾ ملي ٿي جيڪا لاڳو ٿئي ٿي Serializable، ڪنهن به اضافي ڪارناما جي ضرورت نه آهي. سيريلائيزيشن کي ٻار جي طبقي تائين وڌايو ويندو. جڏهن هڪ طبقي مان ورثي ۾ اچي ٿو جيڪو لاڳو ٿئي ٿو Externalizable، توهان کي لازمي طور تي والدين طبقي جي readExternal ۽ writeExternal طريقن کي ختم ڪرڻ گهرجي. ٻي صورت ۾، ٻار طبقي جا شعبا سيريل نه ڪيا ويندا. انهي حالت ۾، توهان کي ياد رکڻو پوندو ته والدين طريقن کي ڪال ڪريو، ٻي صورت ۾ والدين فيلڊ سيريل نه ڪيو ويندو. * * * اسان شايد تفصيل سان ڪيو آهي. تنهن هوندي، اتي هڪ مسئلو آهي جنهن کي اسان نه ڇڪيو آهي، هڪ عالمي نوعيت جو. يعني -

توهان کي Externalizable جي ضرورت ڇو آهي؟

اسان کي سڀ کان ترقي يافته سيريلائيزيشن جي ضرورت ڇو آهي؟ جواب سادو آهي. پهرين، اهو گهڻو وڌيڪ لچڪدار ڏئي ٿو. ٻيو، اهو اڪثر ڪري سگھي ٿو اهم حاصلات مهيا ڪري سگھن ٿا سيريل ٿيل ڊيٽا جي مقدار جي لحاظ کان. ٽيون، ڪارڪردگي جي طور تي هڪ اهڙو پاسو آهي، جنهن بابت اسين هيٺ ڳالهائينداسين . لچڪداريءَ سان هر شيءِ واضح ٿيڻ لڳي. درحقيقت، اسان سيريلائيزيشن ۽ ڊيسيريلائيزيشن جي عمل کي ڪنٽرول ڪري سگھون ٿا جيئن اسان چاهيون ٿا، جيڪو اسان کي ڪلاس ۾ ڪنهن به تبديليء کان آزاد بڻائي ٿو (جيئن مون مٿي چيو آهي، طبقي ۾ تبديليون انتهائي اثر انداز ڪري سگهن ٿيون). تنهن ڪري، مان حجم ۾ حاصل ڪرڻ بابت ڪجهه لفظ چوڻ چاهيان ٿو. اچو ته چئون ته اسان وٽ هيٺيون ڪلاس آهي:
public class DateAndTime{

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

}
باقي غير اهم آهي. فيلڊ int جي قسم مان ٿي سگھي ٿو، پر اھو صرف مثال جي اثر کي وڌائيندو. جيتوڻيڪ حقيقت ۾ فيلڊ شايد intڪارڪردگي سببن لاء ٽائيپ ڪري سگهجي ٿو. ڪنهن به صورت ۾، نقطي واضح آهي. ڪلاس هڪ تاريخ ۽ وقت جي نمائندگي ڪري ٿو. اهو اسان لاء دلچسپ آهي بنيادي طور تي سيريلائيزيشن جي نقطي نظر کان. شايد اهو ڪرڻ جو آسان ترين ڪم هوندو هڪ سادي ٽائم اسٽيمپ کي ذخيرو ڪرڻ. اهو ڊگهو قسم جو آهي، يعني. جڏهن سيريل ڪيو ويندو ته اهو 8 بائيٽ وٺندو. ان کان سواء، هن طريقي جي ضرورت آهي طريقن جي اجزاء کي تبديل ڪرڻ لاء هڪ قدر ۽ واپس، يعني. - پيداوار ۾ نقصان. هن طريقي جو فائدو هڪ مڪمل طور تي چريو تاريخ آهي جيڪا 64 بٽ ۾ فٽ ٿي سگهي ٿي. هي حفاظت جو هڪ وڏو مارجن آهي، اڪثر ڪري حقيقت ۾ گهربل ناهي. مٿي ڏنل ڪلاس 2 + 5 * 1 = 7 بائيٽ وٺندو. پلس اوور هيڊ ڪلاس ۽ 6 شعبن لاءِ. ڇا ھن ڊيٽا کي دٻائڻ جو ڪو طريقو آھي؟ پڪ سان. سيڪنڊ ۽ منٽ رينج ۾ آهن 0-59، يعني. انهن جي نمائندگي ڪرڻ لاءِ، 8 بدران 6 بِٽ ڪافي آهن. ڪلاڪ - 0-23 (5 بِٽ)، ڏينهن - 0-30 (5 بِٽ)، مهينا - 0-11 (4 بِٽ). ڪل، سڀڪنھن شيء کي اڪائونٽ ۾ سال کان سواء - 26 بٽ. int جي سائيز ۾ اڃا 6 بٽ باقي آھن. نظرياتي طور، ڪجهه حالتن ۾ اهو هڪ سال لاء ڪافي ٿي سگهي ٿو. جيڪڏهن نه، هڪ ٻيو بائيٽ شامل ڪرڻ سان ڊيٽا فيلڊ جي سائيز کي 14 بٽ تائين وڌائي ٿو، جيڪا 0-16383 جي حد ڏئي ٿي. اهو حقيقي ايپليڪيشنن ۾ ڪافي کان وڌيڪ آهي. مجموعي طور تي، اسان ضروري معلومات کي ذخيرو ڪرڻ لاء گهربل ڊيٽا جي سائيز کي 5 بائيٽ تائين گھٽائي ڇڏيو آهي. جيڪڏهن نه 4 تائين. نقصان ساڳيو آهي جيئن اڳئين صورت ۾ - جيڪڏهن توهان ذخيرو ٿيل تاريخ کي ذخيرو ڪريو ٿا، پوء تبادلي جي طريقن جي ضرورت آهي. پر مان ان کي هن طريقي سان ڪرڻ چاهيان ٿو: ان کي جدا جدا شعبن ۾ ذخيرو ڪريو ۽ ان کي پيڪيج ٿيل فارم ۾ ترتيب ڏيو. هي اهو آهي جتي اهو استعمال ڪرڻ جو مطلب آهي 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);
}
دراصل، اهو سڀ ڪجهه آهي. سيريلائيزيشن کان پوء، اسان حاصل ڪندا آهيون اوور هيڊ في ڪلاس، ٻه فيلڊز (6 جي بدران) ۽ ڊيٽا جا 5 بائيٽ. جيڪو اڳ ۾ ئي گهڻو بهتر آهي. وڌيڪ پيڪنگنگ خاص لائبريرين ڏانهن ڇڏي سگھجي ٿو. ڏنل مثال بلڪل سادو آهي. ان جو بنيادي مقصد اهو ڏيکارڻ آهي ته ڪيئن ترقي يافته سيريلائيزيشن استعمال ڪري سگهجي ٿي. جيتوڻيڪ سيريل ٿيل ڊيٽا جي مقدار ۾ ممڪن فائدو بنيادي فائدي کان پري آهي، منهنجي راء ۾. مکيه فائدو، لچڪداريءَ کان علاوه... (آسانيءَ سان ايندڙ سيڪشن ڏانهن...) لنڪ جو ذريعو: سيريلائيزيشن جيئن آهي
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION