„Szerializalas jegyzet” változatai közötti eltérés

A VIK Wikiből
Ugrás a navigációhoz Ugrás a kereséshez
(Új oldal, tartalma: „= Szerializálás jegyzet, leírás = Jelen jegyzet, leírás, segédlet nevezzük bárhogy megpróbálja az Objektumorientált Szoftvertervezés és Szoftvertechnológ…”)
 
a (autoedit v2: fájlhivatkozások egységesítése, az új közvetlenül az adott fájlra mutat)
 
(38 közbenső módosítás, amit 2 másik szerkesztő végzett, nincs mutatva)
1. sor: 1. sor:
= Szerializálás jegyzet, leírás =
 
 
Jelen jegyzet, leírás, segédlet nevezzük bárhogy megpróbálja az Objektumorientált Szoftvertervezés és Szoftvertechnológia tárgyakban előszeretettel kérdezett Java szerializálás témaköréből egy áttekinthető, konyhanyelven készült leírást szolgáltatni, sok-sok példával.
 
Jelen jegyzet, leírás, segédlet nevezzük bárhogy megpróbálja az Objektumorientált Szoftvertervezés és Szoftvertechnológia tárgyakban előszeretettel kérdezett Java szerializálás témaköréből egy áttekinthető, konyhanyelven készült leírást szolgáltatni, sok-sok példával.
 +
== Alapok, amiket jó ha tudunk ==
 +
* Alapvetően minden nem statikus és nem tranzies attribútuma egy osztálynak szerializálódik, amely megvalósítja a Serializable interfészt.
 +
* A láthatóság nem befolyásolja a szerializálhatóságot, mind a public, protected és private adattagok szerializálódnak.
 +
* Kiíráskor minden objektum egyszer íródok ki "rendesen", azt követően az adott objektum újboli kiírásakor - feltételezve, hogy a streamet nem zárták be - csupán egy referencia kerül kiírásra, amely referál az először kiírt "rendes" objektumra.
 +
* A szerializálhatóság mint tulajdonság, fennmarad az örökléskor is, tehát ha egy osztály sorosítható akkor annak leszármazottai is kimenthetőek lesznek.
 +
*A szerializálás tiltására van lehetőségünk, a wirteObject metódust kell felüldefiniálnunk abban az osztályban, amelyiket nem szeretnénk szerializálni:
 +
  private void writeObject(ObjectOutputStream o) throws NotSerializableException{
 +
      throw new NotSerializableException("No-no! No Mr. Serializaton!");
 +
  }
 +
<br/>
 +
* Két nagyon fontos metódus játszik fő szerepet a szerializálásban:
 +
**private void '''writeObject''' (ObjectOutputStream out) throws IOException
 +
***A metódus gyakorlatilag teljes kontrollt biztosít a szerializálandó objektum sorosítása felett. A legtöbb esetben egy out.defaultWriteObject() metódushívással kezdődik ezen metódusok implementálása, majd ezt követően lehetőségünk van egyéb adatok sorosítására az erre alkalmas metódusok meghívásával mint pl. az out.writeDouble.
 +
**private void '''readObject'''(ObjectInputStream in) throws IOException, ClassNotFoundException
 +
***A writeObject metódus ellentéte, a korábban szerializált obejktumokat ezzel a metódussal tudjuk beolvasni. Felüldefiniálásakor az implementáció itt is - a writeObject-hez hasonlóan - az automatikusan szerializált adatok automatikus visszaolvasásával kezdődik, ami a in.defaultReadObject() meghívásával történik. Ezek után beolvassuk azon extra adatokat amelyeket korábban a writeObject() metódussal szerializáltunk. Fontos, hogy a típusegyezésre nekünk kell figyelnünk, így beolvasáskor helyesen kell kasztolnunk, illetve a primitív típusok esetén a megfelelő beolvasó metódust kell meghívnunk.
 +
<br />
 +
*'''Egy, két nyalánkság:'''
 +
**private Object '''writeReplace'''() throws ObjectStreamException
 +
***A metódus segítségével létrehozható egy "helyettesítő" objektum. A szerializálás során ez az újonnan létrehozott objektum fog szerializálódni az eredeti helyett.
 +
***Az ObjectOuputStream ellenőrzi, hogy a sorosítani kívánt osztály definiál-e writeReplace() metódust, és ha igen meghívja azt először majd az így visszaadott objektumot fogja végül sorosítani.
 +
**private Object '''readResolve'''() throws ObjectStreamException
 +
***A writeReplace() ellentéte. Ha a metódus definiált az osztályban, akkor az objektum beolvasása előtt, ennek a metódusnak az eredményét "olvassa be" az ObjectInputStream, a korábban szerializált helyett.
 +
**private static final ObjectStreamField[] '''serialPersistentFields'''
 +
***Fontos, hogy ez a korábbiakkal ellentétben nem metódus, hanem egy statikus, nem módosítható tömb az osztályban.
 +
***A tömb használatával lehetőségünk van explicit megadni, hogy az osztály mely attribútumai szerializálódjanak. '''Fontos''', hogy csak a tömbben megjelölt tagváltozók mentődnek ki, tehát hiába van az osztálynak több nem statikus és nem tranziens tagváltozója, csak és kizárólag azon attribútumok fognak szerializálódni amelyek ebben a tömbben szerepelnek!
 +
***A lenti példában beállítottuk, hogy a Dog osztály szerializálásakor csak az age és a name attribútumok mentődjenek le, a többi adat ne. '''Fontos, hogy a tranziensnek jelölt attribútumok is szerializálhatók így!'''
 +
  public class Dog implements Serializable {
 +
      public String name;
 +
      public int age;
 +
      private int ID;
 +
      private String owner;
 +
     
 +
      private static final ObjectStreamField[] serialPersistentFields = {
 +
            new ObjectStreamField("age",Integer.TYPE),
 +
            new ObjectStreamField("name", String.TYPE) };
 +
     
 +
      ...
 +
  }
 +
 
== Korábbi vizsgapéldák ==
 
== Korábbi vizsgapéldák ==
 
=== OOT - 2015. június 2. ===
 
=== OOT - 2015. június 2. ===
15. sor: 53. sor:
 
       }
 
       }
 
   }
 
   }
 +
 +
* Eredmény: x = 0, y = 6
 +
 +
=== OOT - 2015. június 9. ===
 +
  public class A implements Serializable {
 +
     
 +
      private transient int x = 8;
 +
      public int y = 4;
 +
     
 +
      public A () { x = 0; y = 4; }
 +
     
 +
      private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("x", Integer.TYPE) };
 +
     
 +
      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
 +
        in.defaultReadObject();
 +
        x = y + 4;
 +
      }
 +
  }
 +
* Eredmény: x=4, y=0
 +
* [[Media:oot_20150602VizsgaFeladat_20150612.java | Java fájl letöltése]]

A lap jelenlegi, 2017. július 12., 13:59-kori változata

Jelen jegyzet, leírás, segédlet nevezzük bárhogy megpróbálja az Objektumorientált Szoftvertervezés és Szoftvertechnológia tárgyakban előszeretettel kérdezett Java szerializálás témaköréből egy áttekinthető, konyhanyelven készült leírást szolgáltatni, sok-sok példával.

Alapok, amiket jó ha tudunk

  • Alapvetően minden nem statikus és nem tranzies attribútuma egy osztálynak szerializálódik, amely megvalósítja a Serializable interfészt.
  • A láthatóság nem befolyásolja a szerializálhatóságot, mind a public, protected és private adattagok szerializálódnak.
  • Kiíráskor minden objektum egyszer íródok ki "rendesen", azt követően az adott objektum újboli kiírásakor - feltételezve, hogy a streamet nem zárták be - csupán egy referencia kerül kiírásra, amely referál az először kiírt "rendes" objektumra.
  • A szerializálhatóság mint tulajdonság, fennmarad az örökléskor is, tehát ha egy osztály sorosítható akkor annak leszármazottai is kimenthetőek lesznek.
  • A szerializálás tiltására van lehetőségünk, a wirteObject metódust kell felüldefiniálnunk abban az osztályban, amelyiket nem szeretnénk szerializálni:
  private void writeObject(ObjectOutputStream o) throws NotSerializableException{
     throw new NotSerializableException("No-no! No Mr. Serializaton!");
  }


  • Két nagyon fontos metódus játszik fő szerepet a szerializálásban:
    • private void writeObject (ObjectOutputStream out) throws IOException
      • A metódus gyakorlatilag teljes kontrollt biztosít a szerializálandó objektum sorosítása felett. A legtöbb esetben egy out.defaultWriteObject() metódushívással kezdődik ezen metódusok implementálása, majd ezt követően lehetőségünk van egyéb adatok sorosítására az erre alkalmas metódusok meghívásával mint pl. az out.writeDouble.
    • private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
      • A writeObject metódus ellentéte, a korábban szerializált obejktumokat ezzel a metódussal tudjuk beolvasni. Felüldefiniálásakor az implementáció itt is - a writeObject-hez hasonlóan - az automatikusan szerializált adatok automatikus visszaolvasásával kezdődik, ami a in.defaultReadObject() meghívásával történik. Ezek után beolvassuk azon extra adatokat amelyeket korábban a writeObject() metódussal szerializáltunk. Fontos, hogy a típusegyezésre nekünk kell figyelnünk, így beolvasáskor helyesen kell kasztolnunk, illetve a primitív típusok esetén a megfelelő beolvasó metódust kell meghívnunk.


  • Egy, két nyalánkság:
    • private Object writeReplace() throws ObjectStreamException
      • A metódus segítségével létrehozható egy "helyettesítő" objektum. A szerializálás során ez az újonnan létrehozott objektum fog szerializálódni az eredeti helyett.
      • Az ObjectOuputStream ellenőrzi, hogy a sorosítani kívánt osztály definiál-e writeReplace() metódust, és ha igen meghívja azt először majd az így visszaadott objektumot fogja végül sorosítani.
    • private Object readResolve() throws ObjectStreamException
      • A writeReplace() ellentéte. Ha a metódus definiált az osztályban, akkor az objektum beolvasása előtt, ennek a metódusnak az eredményét "olvassa be" az ObjectInputStream, a korábban szerializált helyett.
    • private static final ObjectStreamField[] serialPersistentFields
      • Fontos, hogy ez a korábbiakkal ellentétben nem metódus, hanem egy statikus, nem módosítható tömb az osztályban.
      • A tömb használatával lehetőségünk van explicit megadni, hogy az osztály mely attribútumai szerializálódjanak. Fontos, hogy csak a tömbben megjelölt tagváltozók mentődnek ki, tehát hiába van az osztálynak több nem statikus és nem tranziens tagváltozója, csak és kizárólag azon attribútumok fognak szerializálódni amelyek ebben a tömbben szerepelnek!
      • A lenti példában beállítottuk, hogy a Dog osztály szerializálásakor csak az age és a name attribútumok mentődjenek le, a többi adat ne. Fontos, hogy a tranziensnek jelölt attribútumok is szerializálhatók így!
  public class Dog implements Serializable {
     public String name;
     public int age;
     private int ID;
     private String owner;
     
     private static final ObjectStreamField[] serialPersistentFields = { 
           new ObjectStreamField("age",Integer.TYPE), 
           new ObjectStreamField("name", String.TYPE) };
      
     ...
  }

Korábbi vizsgapéldák

OOT - 2015. június 2.

  public class A implements Serializable {
     private int x = 1;
     public transient int y = 2;
     
     private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("y", Integer.TYPE) };
     
     public A() { x = 3; y = 4; }
     
     public Object writeReplace() throws ObjectStreamException {
           A a = new A(); a.x = 5; a.y = 6; return a;
     }
  }
  • Eredmény: x = 0, y = 6

OOT - 2015. június 9.

  public class A implements Serializable {
     
     private transient int x = 8;
     public int y = 4;
     
     public A () { x = 0; y = 4; }
     
     private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("x", Integer.TYPE) };
     
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
        in.defaultReadObject();
        x = y + 4;
     }
  }