MokaByte
Numero 07 - Aprile 1997
|
|||
|
|
||
Massimo Carli |
|||
Che cosa é la serializzazione
L’utilizzo di
questa tecnica permette di ovviare ad un inconveniente molto frequente
nella programmazione di applicazioniche permettano la creazione e la editazione
di una qualche struttura dati. Supponiamo di avere una applicazione che
permette di creare ed editare una lista di oggetti. Una volta che questa
struttura dati è stata creata vi è il problema di salvarne
il contenuto per eventualmente,ripristinarlo in un secondo tempo.
Prima del JDK1.1
come si doveva fare? Bisognava decidere un certo protocollo di memorizzazione
su un file. Sedovevamo salvare dei record di dati di struttura simile avevamo
dei vantaggiin quanto scrivevamo sullo stream una struttura fissa in modo
testo o altro. Ma le cose divenivano sempre più complicate se la
struttura datiera un po’ più complessa. Se la struttura consisteva
in un albero,oggetti legati tra loro da una relazione padre figlio, o liste
bilatereo altro, il problema assumeva una certa dimensione. Bisognava implementare
due enormi metodi di conversione della struttura in un qualcosa di sequenziale,salvarlo
e poi ripristinarlo e ricostruire la struttura originaria. Con la serializzazione
questo problema diventa una banalità.
Come si indica che un oggetto è serializzabile
In Java non è
cosa rara incontrare delle interfacce che non presentano la dichiarazione
di metodi. Esse servono semplicemente a segnare o firmare una determinata
classe. Nel nostro caso la interfaccia che permette di stabilire che una
classe è serializzabileè la java.io.Serializable.
Se un oggetto implemental’interfaccia Serializable, esso è
serializzabile cioè può essere salvato, o meglio reso persistente,
e poi ripristinato. La cosa importante è che l’oggetto ripristinato
abbia le stesse proprietà dell’oggetto salvato. Questo non è
completamentevero in quanto vi è la possibilità di definire
alcune proprietà come transient
per cui ne viene salvata
l’istanza ma in fase di ripristino i suoi campi assumono i loro valori
di default.
Supponiamo di
avere una classe di nome Struttura. Per renderla serializzabile
basterà scrivere
publicclass Struttura
extends Parent implements java.io.Serializable {
....................
...................
}
Parent
è una ipotetica classe di cui Struttura è estensione
(ovviamente può anche non esserci, è solo un esempio). Una
cosa da dire assolutamente è che, per essere serializzabile, una
classe deve utilizzare alsuo interno classi serializzabili. Se una variabile
pubblica di Struttura non fosse serializzabile, essa non
sarebbe effettivamente serializzabile. Il processo di serializzazione,
infatti, è ricorsivo.
Con il JDK1.1esiste
uno strumento che permette di verificare se un a classe è, oppure
no, serializzabile. Questo si chiama serialver.
Chiamando questo
programma con l’opzione -show apparirà una finestra nella
quale metterete il nome completo della classe che volete esaminare. Se
la classe è serializzabile apparirà un valore identificativo
della classe stessa, altrimenti non apparirà nulla.
In questo modo
potrete verificare le vostre classi. La cosa, a dire ilvero non funziona
molto bene in quanto se provate a verificare se la classe java.awt.Image
è serializzabile avete risposta positivamentre se poi provate a
serializzarla avete un errore. Questo èun bug conosciuto della JDK1.1
che si estende, oltre che alla classe Image, anche ai TextComponent nella
beta3. Mah! Evidentemente il serialver verifica se la classe implementa
Serializable insieme a tuttele classi utilizzate e niente
altro, senza verificarne il funzionamento.
Il numero che
appare nel serialver non è altro che un identificativo della classe
e della sua versione. Infatti,quando una struttura viene serializzata,
può capitare che diverseistanze di una stessa siano scritte sullo
stream. Nel caso in cui questoavvenga, la prima volta si scriverà
la classe con tutte le sue informazionie successivamente si scriverà
solamente l’identificativo della classecon i valori caratteristici dell’istanza.
In questo modo si ottiene anche una buona compressione dei dati scritti.
Un’altra cosa
da sottolineare è la gestione delle versioni diverse della stessa
classe. Se si rende persistente una classe e la si ripristina bisognerà
fare in modo che il fileclass della classe di cui si dispone in
fase di ripristino non siaconsiderevolmente differente da quella a disposizione
in fase di creazione. Per considerevolmente differente intendiamo che la
interfaccia che mettea disposizione non sia diversa. In questo caso si
avrebbe quella che èla eccezione della serializzazione cioè
java.io.ObjectStreamException.
Come si rende un oggetto persistente
Ora che abbiamo
brevemente descritto che cosaè la persistenza, vediamo come si può
serializzare una classe.La cosa è molto semplice in quanto il JDK
mette a disposizione quelliche sono gli strumenti essenziali alla serializzazione.
Questi sono l’interfacciajava.io.Serializable e le due nuove
classi java.io.ObjectInputStreamed java.io.ObjectOutputStream.
Queste classi implementanole interfaccia java.io.ObjectInput
ed java.io.ObjectOutputrispettivamente. Queste, a loro volta
estendono le interfacce java.io.DataInpute java.io.DataOutput
introducendo i metodi readObjecte writeObject. Attraverso
questi due metodi è possibile primascrivere e poi rileggere e ricostruire
un qualunque oggetto serializzabile.
Supponiamo di
voler salvare su un file dinome restore.ser un oggetto che abbiamo
creato in una qualche altraparte di una applicazione. Chiamiamo questo
oggetto salvato. Scriviamo,allora, il metodo scrivi che permette
il salvataggio dell’oggettoindicato sul file.
Public void scrivi () {Il metodo non fa altro che legare un ObjectOutputStreamad un FileOuputStream per poter scrivere sul file l’oggettoattraverso il metodo writeObject.
try{
fos = new FileOutputStream ("restore.ser");
oos = new ObjectOutputStream(fos);
oos.writeObject(salvato);
oos.close();
}
catch (Ioexception ioe){
System.out.println("Errore:"+ioe.toString());
}// fine catch
}// fine metodo scrivi
Public void leggi () {Il metodo di lettura è molto semplice. L’unica cosa da considerare con attenzione riguarda l’operazione di cast da fare all’atto del readObject. Infatti essa ritorna un Objectper cui tale operazione si rende necessaria. Nel nostro caso abbiamo eseguitouna operazione di cast relativamente al tipo TipoSalvato,tipo realtivo all’oggetto salvato.
try{
fis = new FileInputStream ("restore.ser");
ois = new ObjectInputStream(fis);
salvato = (TipoSalvato)(ois.readObject());
ois.close();
}
catch (Ioexception ioe){
System.out.println("Errore:"+ioe.toString());
}// fine catch
}// fine metodo leggi
Conclusioni
In questo breve
articolo abbiamo visto checosa è la serializzazione e come si rende
persistente un oggetto. Questa tecnica è molto utile e permette
di risolvere, in poche righedi codice, problemi che in precedenza portavano
via molto tempo, relativamentealla memorizzazione e ricostruzione di strutture
dati complesse. Ovviamente la serializzazione non solo quello descritto
qui ma offre tecniche piùsofisticate per la gestione delle versioni
relativamente alle conversionidi tipo tra versioni diverse di stesse classi.
Magari approfondiremo questiargomenti in un successivo articolo.
|
||
|
||
MokaByte ricerca
nuovi collaboratori
|
||
|