Aceasta interfata nu declara nici metode, nici atribute, serveste doar pentru identificarea obiectelor serializabile. Clasele care nu implementeaza aceasta interfata nu vor putea fi serializate sau deserializate. Operatia de deserializare presupune ca clasa obievtului poseda si un constructor cu vizibilitate publica si fara argumente. Atributele obiectului vor fi initializate dintr-un flux de date. In cazul serializarii unui obiect care apartine unui graf de obiecte daca se ajunge la un obiect care nu implementeaza interfata Serializable, atunci se genereaza exceptia NoSerializableException . Clasele care necesita o tratare speciala pe parcursul serializarii si a deserializarii trebuie sa implementeze urmatoarele doua metode cu urmatoarele signaturi:
private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
Metoda writeObject() este responsabila pentru salvarea starii obiectului, iar metoda readObject() are responsabilitatea restaurarii starii obiectului. Salvarea starii, adica a atributelor intr-un flux ObjectOutputStream se efectueaza cu metoda writeObject() respectiv cu metodele writeInt(), writeDouble() etc., metodele interfetei DataOutput.
import java.util.*;
import java.io.*;
class AccountSer implements Serializable {
private String username;
private String password;
public AccountSer( String username, String password ){
System.out.println("Constructor Account( String,
String )");
this.username = username;
this.password = password;
}
public AccountSer(){
System.out.println("Default Constructor Account()");
}
public void readObject( ObjectInputStream in ) throws ClassNotFoundException
{
System.out.println("Method readObject, class
Account");
try{
username = ( String )in.readObject();
password = ( String )in.readObject();
}
catch( IOException e ){
System.out.println(e);
}
}
public void writeObject( ObjectOutputStream out ) throws IOException
{
System.out.println("Method writeObject, class
Account");
out.writeObject( username );
out.writeObject( password );
}
public String toString(){
return username+password;
}
public static void main( String args[] )
{
System.out.println("Creating an object");
AccountSer a = new AccountSer("MyName","MyPassword");
try{
System.out.println("Saving the
object");
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("Account.ser"));
out.writeObject( a );
out.close();
System.out.println("Restoring the
object");
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("Account.ser"));
Account b = (Account) in.readObject();
in.close();
System.out.println( b );
}
catch( Exception e)
{
System.out.println( e );
}
}
}
void |
readExternal(ObjectInput
in) Obiectul care implementeaza aceasta metoda poate s-o utilizeze pentru restaurarea starii obiectelor cu metodele readObject() pentru obiecte oarecare, siruri de caractere(String) si tablouri, iar metodele din DataInput pentru tipuri de date primitive. |
void |
writeExternal(ObjectOutput
out) Obiectul care implementeazaaceasta metoda poate s-o utilizeze pentru salvarea starii obiectelor cu metodele readObject() pentru obiecte oarecare, siruri de caractere(String)si tablouri, iar metodele din DataInput pentru tipuri de date primitive. |
In exemplul urmator vom construi un server care rezolva cateva tipuri de cereri. Gama serviciilor oferite de acest server se poate extinde prin adaugarea a noi clase la aplicatie.Pentru diferite tipuri de cereri seintroduce o clasa de baza serializabila cu numele Cerere.
public class Cerere implements Serializable {Aceasta clasa fiind serializabila toate clasele derivate din aceasta vorfi implicit serializabile. Vom deriva din aceasta clasa o clasa CerereData .Clasa defineste o cerere pentru data calendaristica. Ori de cate ori serverul primeste un asemenea obiect trimite ca si raspuns un obiect de tip java.util.Date. O alta clasa derivata din aceasta esete CerereCalcul care va fi superclasa tuturor claselor cereri de tip calcul. Aceasta clasa va avea o metoda Objectexecute() pentru a executa calcului dorit. De fapt clasa CerereCalcul serveste ca clasa de baza si de aceea la acest nivel nu efectueza niciun calcul, returneaza null. Clasele derivate vor redefini aceasta metodacompletand cu efectuarea calculelor specifice acelor clase. Un exemplude clasa care efectueaza un calcul va fi clasa CerereRidicareLaPutere.
}
Serverul va avea o arhitectura paralela, pentru fiecare client se creaza un fir de executie ( un obiect DeservireClient ) si toate cererile suntrezolvate de catre acesta.
Diagrama de clasa a aplicatiei:
Sursele:
import java.io.Serializable;
public class Cerere implements Serializable
{
}
public class CerereData extends Cerere
{
}
public class CerereCalcul extends Cerere
{
public java.lang.Object execute()
{
return null;
}
}
public class CerereRidicareLaPatrat extends CerereCalcul
{
private int n;
public CerereRidicareLaPatrat(int n)
{
this.n = n;
}
public java.lang.Object execute()
{
return new Integer( n* n );
}
}
import java.io.IOException;
public class Server
{
public static void main(String[] args) throws IOException
{
if( args.length != 1 ){
System.out.println("Utilizare java Server <port>");
System.exit( 0 );
}
java.net.ServerSocket ss = new java.net.ServerSocket( Integer.parseInt( args[ 0 ] ));
while( true )
new DeservireClient( ss.accept() ).start();
}
}
import java.net.Socket;
import java.net.SocketException;
public class DeservireClient extends Thread
{
private Socket clientSocket;
public DeservireClient(java.net.Socket clientsocket) throws SocketException
{
this.clientSocket = clientsocket;
}
public void run()
{
try{
java.io.ObjectInputStream in = new java.io.ObjectInputStream( clientSocket.getInputStream());
java.io.ObjectOutputStream out = new java.io.ObjectOutputStream( clientSocket.getOutputStream());
while( true ){
out.writeObject( executaCerere( in.readObject()));
out.flush();
}
}
// Clientul inchide conexiunea
catch( java.io.EOFException e1 ){
try{
clientSocket.close();
}
catch( java.io.IOException e2 ){ System.out.println( e2 ); }
}
// Eroare I/O
catch( java.io.IOException e2 ){ System.out.println( e2 ); }
// Cerere necunoscuta
catch( ClassNotFoundException e3 ){ System.out.println( e3 ); }
}
public java.lang.Object executaCerere(java.lang.Object cerere)
{
if( cerere instanceof CerereData )
return new java.util.Date();
else
if( cerere instanceof CerereCalcul )
return ((CerereCalcul) cerere).execute();
else
return null;
}
}
public class Client
{
public static void main(String[] args)
{
if( args.length != 2 )
{
System.out.println("Utilizare java Client <numehost> <porthost> ");
System.exit( 0 );
}
try{
java.net.Socket socket = new java.net.Socket( args[ 0 ] , Integer.parseInt( args[ 1 ] ));
java.io.ObjectOutputStream out = new java.io.ObjectOutputStream( socket.getOutputStream());
java.io.ObjectInputStream in = new java.io.ObjectInputStream( socket.getInputStream());
// Se trimite prima cerere
out.writeObject( new CerereData() );
out.flush();
System.out.println( in.readObject());
// Se trimite a doua cerere
out.writeObject( new CerereRidicareLaPatrat( 5 ) );
out.flush();
System.out.println( in.readObject());
socket.close();
}
// Eroare I/O
catch( java.io.IOException e ){
System.out.println( e );
}
// Tip raspuns necunoscut
catch( ClassNotFoundException e1 ){
System.out.println( e1 );
}
}
}