Sunteți pe pagina 1din 4

1

Serializarea obiectelor

Facilitile legate de serializare/deserializare apar n pachetul java.io.

1. Necesitatea serializrii i deserializrii obiectelor


n multe situaii apare necesitatea ca unul sau mai multe obiecte s poat fi memorate pentru a fi folosite i dup ncheierea aplicaiei care le-a creat. Pentru aceasta starea lor trebuie salvat ntr-un mod care s permit refacerea lor ulterioar. Java ofer mecanismele de serializare i deserializare, care realizeaz tocmai salvarea, respectiv refacerea obiectelor. Una dintre aplicaiile evidente ale acestor mecanisme const n serializarea obiectelor pe un sistem, urmat de transmiterea lor la distan i deserializarea lor pe o nou main gazd pentru a fi folosite n continuare. Serializarea const n memorarea, ntr-un anumit format, a strii obiectelor ntr-un tablou de octei sau ntr-un fiier. Acestea au un caracter serial: pot accepta numai secvene de octei. De aici deriv denumirile de serializare/deserializare. Facilitatea ca obiectele s poat "supravieui" i dup teminarea executrii programului care le-a creat se mai numete persistena datelor. n exemplele care urmeaz vor presupune c serializarea se va face n cadrul unui director, iar deserializarea se va realiza din alt director. Ele vor fi numite ad-hoc director surs i director destinaie i nu sunt neaprat distincte.

2. Un prim exemplu
Exemplul 4. Directorul surs conine clasa Angajat:
import java.io.*; public class Angajat implements Serializable { String nume; int varsta; int salariu; static String firma; public Angajat(String n, int v, int s) { nume=n; varsta=v; salariu=s; } public void print() { System.out.println("Firma:\t\t" + firma + "\n" + "Nume:\t\t" + nume + "\n" + "Varsta:\t\t" + varsta + "\n" + "Salariul:\t" + salariu + "\n"); }

i clasa Serial:

2
import java.io.*; public class Serial { public static void main(String[] sir) throws Exception { Angajat.firma = "SRL Serial"; Angajat Unu = new Angajat("Vasile", 25, 1485); Angajat Doi = new Angajat("Ion", 24, 420); FileOutputStream fos = new FileOutputStream("Serial"); ObjectOutputStream oos = new ObjectOutputStream(fos); // oos.writeUTF(Angajat.firma); oos.writeObject(Unu); oos.writeObject(Doi); oos.close(); fos.close(); } }

Facem deocamdat abstracie de coninutul comentariilor de sfrit de linie. Clasa ObjectOutputStream extinde clasa abstract OutputStream. Prin invocarea metodei writeObject se realizeaz serializarea (ntr-un mod standard) a obiectelor create i scrierea rezultatului serializrii n fluxul de ieire. Clasa Angajat implementeaz interfaa Serializable. Prin abuz de limbaj vom numi clas serializabil o clas ce implementeaz aceast interfa. S reinem c numai instanele unei clase serializabile pot fi serializate. Mai observm c un flux de serializare poate conine mai multe obiecte. Presupunem n continuare c n directorul destinaie apar (de exemplu au fost copiate) fiierele Angajat i Serial, precum clasa Serial1:
import java.io.*; public class Serial1 { public static void main(String args[]) throws Exception { FileInputStream fis = new FileInputStream("Serial"); ObjectInputStream ois = new ObjectInputStream(fis); // Angajat.firma = ois.readUTF(); Angajat Unu = (Angajat) ois.readObject(); Angajat Doi = (Angajat) ois.readObject(); Unu.print(); Doi.print(); ois.close(); fis.close(); } }

Clasa ObjectInputStream extinde clasa abstract InputStream. Prin invocarea metodei readObject se realizeaz deserializarea (ntr-un mod standard) a obiectelor din fluxul de intrare. Metoda readObject ntoarce un obiect de tipul Object, ceea ce face necesar conversia explicit la tipul Angajat. S observm c la ieire, n dreptul numelui firmei apare null. Aceasta se datoreaz faptului c n mecanismul de serializare nu sunt incluse i cmpurile statice. Explicaia const n aceea c serializarea se refer la obiecte, iar cmpurile statice sunt variabile de clas. Dac vom transforma comentariile de sfrit de linie din clasele de mai sus n instruciuni efective, atunci i cmpul static firma va fi inclus n procesul de serializare. Drept urmare, la ieire va aprea i numele firmei. Deci pentru a fi i ele transmise, cmpurile statice trebuie incluse explicit n fluxul de ieire.

3. Ce se transmite la serializare?
Rspundem parial, menionnd c nu sunt transmise cmpurile statice i nici corpurile metodelor: este transmis numai signatura lor. Exemplul 5. Serializm un obiect al urmtoarei clase:
import java.io.*; public class C implements Serializable { int x,y; C(int a, int b) { x = a; y = b; } } void print() { System.out.println("Suma =\t" + (x+y)); }

Dac la deserializare n directorul destinaie n metoda print a clasei UnuC nlocuim (x+y) prin (x*y), iar obiectul de tipul UnuC obinut prin deserializare invoc aceast metod, la ieire va aprea produsul (i nu suma) celor dou cmpuri. ntrebare: Cte obiecte sunt serializate la serializarea unui obiect? Intervine noiunea de graf asociat unui obiect. Graful asociat unui obiect const din obiectul respectiv, dar i din obiectele referite direct sau indirect de el. La serializarea unui obiect este serializat ntregul graf asociat obiectului respectiv. Aceast facilitate este foarte util i poate fi folosit de exemplu pentru: - transmiterea unui arbore; este suficient s serializm rdcina i vor fi serializate toate vrfurile arborelui, mpreun cu structura de arbore; - transmiterea unei liste circulare: este suficient s serializm primul element al listei i vor fi serializate toate elementele listei, mpreun cu structura de list circular; n particular, serializarea "nu se ncurc" dac un obiect din graful asociat se autorefer. Exemplul 6. Serializarea unei liste circulare nevide. Directorul surs conine clasa element:
import java.io.*; import java.util.*; class element implements Serializable { int info; element leg; static element p,u; element() { } element(int i) { info = i; } void creare() { element x; Scanner sc = new Scanner(System.in); int i = sc.nextInt(); p = new element(i); u = p; while ( sc.hasNextInt() ) { x = new element( sc.nextInt() ); u.leg = x; u = x; } u.leg = p; }

4
String parcurg(element x) { if (x.leg == p) return x.info + ""; else return x.info + "\t" + parcurg(x.leg); } }

precum i clasa Lista1:


import java.io.*; public class Lista1 { public static void main(String[] sir) throws Exception { element Ob = new element(); Ob.creare(); System.out.println(Ob.parcurg(element.p)); FileOutputStream fos = new FileOutputStream("lista"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(element.p); oos.close(); fos.close(); } }

Metoda principal a clasei Lista1 construiete o list nlnuit circular format din ntregii citii de la intrare pn la ntlnirea unei entiti care nu este un ntreg. Capul listei apare n cmpul static p al clasei elem. La serializarea lui p sunt de fapt serializate toate elemetele (obiectele) din list, adic ntreg graful asociat acestui obiect, precum i structura de list. ntr-adevr, dac n directorul destinaie includem clasa element i urmtoarea clas Lista2:
import java.io.*; public class Lista2 { public static void main(String[] sir) throws Exception { FileInputStream fis = new FileInputStream("lista"); ObjectInputStream ois = new ObjectInputStream(fis); element.p = (element) ois.readObject(); element Ob = new element(); System.out.println( Ob.parcurg(element.p) ); ois.close(); fis.close();

} }

atunci la executarea metodei principale vor fi listate toate elementele listei.

Evaluare