„Szerializalas jegyzet” változatai közötti eltérés
A VIK Wikiből
a autoedit v2: fájlhivatkozások egységesítése, az új közvetlenül az adott fájlra mutat |
|||
(20 közbenső módosítás, amit 2 másik szerkesztő végzett, nincs mutatva) | |||
2. sor: | 2. sor: | ||
== Alapok, amiket jó ha tudunk == | == 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. | * 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á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: | *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: | ||
20. sor: | 22. sor: | ||
**private Object '''readResolve'''() throws ObjectStreamException | **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. | ***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 == | ||
35. sor: | 53. sor: | ||
} | } | ||
} | } | ||
* Eredmény: x = 0, y = 6 | |||
=== OOT - 2015. június 9. === | === OOT - 2015. június 9. === | ||
51. sor: | 71. sor: | ||
} | } | ||
} | } | ||
* Eredmény: x=4, y=0 | |||
* [[Media:oot_20150602VizsgaFeladat_20150612.java | Java fájl letöltése]] |
A lap jelenlegi, 2017. július 12., 14: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.
- private void writeObject (ObjectOutputStream out) throws IOException
- 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!
- private Object writeReplace() throws ObjectStreamException
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; } }
- Eredmény: x=4, y=0
- Java fájl letöltése