Ebben a cikkben a szerializáció kerül bemutatásra, amelynek segítségével egy objektum állapota bájtokban eltárolható.

Miről is van szó?

A szerializáció segítségével egy objektum bájt-sorozatként reprezentálható egy fájlban. Ez a fájl információt fog tartalmazni az objektum típusáról és minden adattagjáról. Vagyis az objektum állapotát bájtokban eltárolhatjuk.
A deszerializáció során ebből a fájlból kiolvasva az adatokat, újra létrehozható lesz az objektum.


A legfőbb erénye a technikának, hogy JVM független, vagyis az objektum állapotok elmenthetők, adatbázisban tárolhatók, socketen átküldhetők, stb… Ebből következik, hogy különböző platformok közt is működik, azaz szerializálunk az egyik platformon, majd egy teljesen másikon pedig újra létrehozhatjuk az objektumot.

Néhány oprendszer közeli osztály nem szerializálható, például: Thread, OutputStream, Socket.

A szerializáció építőelemei

Egy osztályt szerializálhatóvá tehetünk, ha implementáljuk a java.io.Serializable interfészt. Ennek az interfésznek nincsenek metódusai, vagy adattagjai, szóval nem kell semmit felüldefiniálnunk. Miért is kell akkor implementálni? Egyszerűen azért, mert szemantikailag ezzel az ún. marker interfésszel jelezhetjük a szerializálhatóságot.


A java.io.ObjectInputStream és a java.io.ObjectOutputStream stream osztályok tartalmazzák a szükséges metódusokat, amelyek egy objektum fájlba írását, vagy annak visszaolvasását lehetővé teszik.


A java.io.FileInputStream és a java.io.FileOutputStream osztályok használatát a stream objektumok paraméterei igénylik. Ezek segítségével adható meg maga a fájl amibe írni, vagy amiből olvasni szeretnénk. A lentebb látható példából minden ki fog derülni, semmi pánik.


Két fontos függvényt kell még megemlíteni. Az egyik az ObjectOutputStream writeObject() metódusa, amellyel a megadott fájlba kiírható (menthető) az adott objektum:

public final void writeObject(Object obj) throws IOException  

A másik az ObjectInputStream readObject() metódusa, amelynek segítségével a megadott fájlból vissza lehet olvasni (újra létre lehet hozni) egy objektumot:

public final Object readObject() throws IOException, ClassNotFoundException

Tipp: a beolvasás után használjuk az instanceof operátort, majd kasztoljuk az objektumot.

Példaprogram

Ebben a szakaszban, a fentebb bemutatott lépéseket mutatjuk az alábbi példaprogramban. Egy Point objektumot fogunk szerializálni. A Point osztály így fest (lényeg az implementálandó interfész):

package hu.utils;

public class Point implements Serializable {
    private int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public String toString() {
        return "(" + x + ", " + y + ")";
    }
}

A főosztály pedig tartalmazza a szerializáció lépéseit (write és read függvények az érdekesek):

package hu;

import hu.utils.Point;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Test {
    private static final String FILENAME = "save.txt";
    
    public static void main(final String[] args) {
        write( new Point(4, 7) );
        read();
    }
    
    private static void write(final Point point) {
        FileOutputStream fos;
        ObjectOutputStream oos;
        try {
            fos = new FileOutputStream(FILENAME);
            oos = new ObjectOutputStream(fos);
            
            oos.writeObject(point);
            oos.close();
        } catch (FileNotFoundException ex) {
            System.out.println("FileOutputStream - hiba");
        } catch (IOException ex) {
            System.out.println("ObjectOutputStream - hiba");
        }
    }
    
    private static void read() {
        FileInputStream fis;
        ObjectInputStream ois;
        try {
            fis = new FileInputStream(FILENAME);
            ois = new ObjectInputStream(fis);
            
            Object obj = ois.readObject();
            
            if (obj instanceof Point) {
                Point point = (Point) obj;
                System.out.println(point.toString());
            }
        } catch (FileNotFoundException ex) {
            System.out.println("FileInputStream - hiba");
        } catch (IOException ex) {
            System.out.println("ObjectInputStream - hiba");
        } catch (ClassNotFoundException ex) {
            System.out.println("readObject() - hiba");
        }
    }
}

Ajánló

Cimkék: ,

Az Eötvös Loránd Tudományegyetem Informatikai Karának hallgatója vagyok. Jelenleg az Információs Rendszerek tanszék Tudáskezelő laborjában dolgozom.