Encuesta

¿Qué servidor de aplicaciones empleas mayormente para despliegue?

01-10-2008 - 323 votos

Destacados Agenda

Más eventos |

(1)

Serializacrión en Java

16/09/2001 00:00 emili

Serialización de objetos en Java

Fecha de creación: 10.9.2001
Revisión 1.1 (27.10.2001)

Emili Miedes de Elías
emiedes@iti.upv.es

Copyright (c) 2002, Emili Miedes de Elías. Este documento puede ser distribuido solo bajo los términos y condiciones de la licencia de Documentación de javaHispano v1.0 o posterior (la última versión se encuentra en http://www.javahispano.org/licencias/).

Introducción

La serialización de un objeto consiste en obtener una secuencia de bytes que represente el estado de dicho objeto. Esta secuencia puede utilizarse de varias maneras (puede enviarse a través de la red, guardarse en un fichero para su uso posterior, utilizarse para recomponer el objeto original, etc.).

Estado de un objeto

El estado de un objeto viene dado, básicamente, por el estado de sus campos. Así, serializar un objeto consiste, básicamente, en guardar el estado de sus campos. Si el objeto a serializar tiene campos que a su vez son objetos, habrá que serializarlos primero. Éste es un proceso recursivo que implica la serialización de todo un grafo (en realidad, un árbol) de objetos. Además, también se almacena información relativa a dicho árbol, para poder llevar a cabo la reconstrucción del objeto serializado.

En ocasiones puede interesar que un atributo concreto de un objeto no sea serializado. Esto se puede conseguir utilizando el modificador transient, que informa a la máquina virtual de Java de que no nos interesa mantener el valor de ese atributo para serializarlo o hacerlo persistente.

Ejemplo:

public class MiFecha
{
	protected int n;
	protected Date fecha;
	protected transient long s;
	...
}

En este ejemplo, los atributos n y fecha serán incluídos en la secuencia de bytes resultante de serializar un objeto de clase MiFecha. El atributo s no será incluído, por tener el modificador transient.

Objetos serializables. Interfaz Serializable

Un objeto serializable es un objeto que se puede convertir en una secuencia de bytes. Para que un objeto sea serializable, debe implementar la interfaz java.io.Serializable. Esta interfaz no define ningún método. Simplemente se usa para marcar aquellas clases cuyas instancias pueden ser convertidas a secuencias de bytes (y posteriormente reconstruídas). Objetos tan comunes como String, Vector o ArrayList implementan Serializable, de modo que pueden ser serializados y reconstruídos más tarde.

Para poder serializar un objeto no hay más que declarar el objeto como serializable:

public class MiClase implements java.io.Serializable

El sistema de ejecución de Java se encarga de hacer la serialización de forma automática.

Ejemplos

Almacenamiento de objetos

Es posible utilizar los mecanismos de serialización disponibles para serializar un objeto guardándolo en un fichero y para realizar el proceso inverso, recuperándolo desde el fichero.

	FileOutputStream fos = new FileOutputStream("fichero.bin");
	FileInputStream fis = new FileInputStream("fichero.bin");
	ObjectOutputStream out = new ObjectOutputStream(fos);
	ObjectInputStream in = new ObjectInputStream(fis);

	ClaseSerializable o1 = new ClaseSerializable();	
	ClaseSerializable o2 = new ClaseSerializable();	

	// Escribir el objeto en el fichero
	out.writeObject(o1);
	out.writeObject(o2);
	...
	// Leer el objeto del fichero (en el mismo orden !!)
	o1 = (ClaseSerializable)in.readObject();
	o2 = (ClaseSerializable)in.readObject();

Envío de objetos por la red

También es posible enviar un objeto serializado a través de la red. La diferencia consiste en que ahora se utilizan streams de distinto tipo.

	Socket socket = new Socket(maquina, puerto);
	OutputStream os = socket.getOutputStream();
	InputStream is = socket.getInputStream();
	ObjectOutputStream out = new ObjectOutputStream(os);
	ObjectInputStream in = new ObjectInputStream(is);

	PeticionSerializable ps = new PeticionSerializable();
	RespuestaSerializable rs;

	// Escribir una petición en el socket
	out.writeObject(ps);
	// Recibir del socket la respuesta
	rs = (RespuestaSerializable)in.readObject();

Serialización en RMI

En RMI, la serialización se utiliza de forma casi transparente al usuario. Concretamente, se utiliza en el paso de parámetros y retorno de valores de las invocaciones a métodos de objetos remotos. Por ejemplo, cuando hacemos una invocación remota del tipo

	retorno obj.metodo(param);

ocurre el siguiente proceso, de forma transparente al usuario:
  1. (Local) El objeto param se serializa y se envía al objeto remoto como una secuencia de bytes

  2. (Remoto) Se obtiene el objeto original a partir de la secuencia de bytes

  3. (Remoto) Se ejecuta el método y se obtiene un valor de retorno

  4. (Remoto) El valor de retorno se serializa y se envía como una secuencia de bytes

  5. (Local) Se obtiene el retorno a partir de la secuencia de bytes

Para que esta invocación se lleve a cabo, es necesario que tanto los parámetros de las invocaciones remotas como los valores devueltos pertenezcan a clases serializables.

Serialización personalizada

En ocasiones puede interesar tomar el control sobre el proceso de serialización de una clase en concreto. Esto se puede hacer sobrecargando los métodos writeObject y readObject de la clase cuya serialización se quiere controlar.

En realidad, no se puede hablar de sobrecarga, puesto que estos métodos no están definidos en java.lang.Object. Este punto es un poco oscuro. Puede consultarse el API al respecto (método writeObject(Object) de ObjectOutputStream y método readObject() de ObjectInputStream) y el JavaTutorial (Essential Java Classes -> Reading and Writing (but no 'rithmetic) -> Object Serialization -> Providing Object Serialization for Your Classes).

Para personalizar la serialización de un objeto, basta añadir un método tal que:

	private void writeObject (ObjectOutputStream stream)
	throws IOException
	{
		stream.defaultWriteObject();

		...
	}

Es necesario respetar exactamente tanto la signatura del método como la primera acción a realizar. A continuación pueden añadirse otras acciones que escriban en el stream dado.

También será necesario añadir un método para hacer el paso inverso:

	private void readObject (ObjectInputStream stream)
	throws IOException
	{
		stream.defaultReadObject();

		...
	}

En [1] hay un ejemplo muy sencillo de uso de estos dos métodos. Con los println es posible comprobar que realmente se ejecutan cuando se produce la serialización y la reconstrucción de un objeto Prueba.

Interfaz Externalizable

Existe una interfaz en java.io llamada Externalizable que permite obtener un mayor control sobre el proceso de serialización y reconstrucción de nuestros objetos. Esta interfaz define dos métodos, writeExternal y readExternal, que se encargan de serializar y reconstruir un objeto, respectivamente.

La serialización mediante Externalizable requiere de un mayor cuidado. De forma automática, sólo se guarda información relativa a la identidad de la clase del objeto que se está serializando. No se guarda automáticamente ni su estado ni información relativa a sus superclases. Por ello, en la implementación de writeExternal hay que guardar explícitamente el estado de aquellos atributos que nos interesen, incluídos los heredados.

A la hora de implementar writeExternal y readExternal, se ha de tener muy en cuenta la serialización de las clases superiores en el grafo de herencia y coordinar la implementación de estos métodos con la de los mismos métodos en clases superiores.

Recursos

[1] Prueba.java

Acerca del autor

Emili Miedes de Elías
Emili trabaja en el Instituto Tecnológico de Informática (Universidad Politécnica de Valencia) desarrollando en Java. En sus ratos libres, colabora con javaHispano y desarrolla software opensource (buscar por emiedes en SourceForge).

Volver a actualidad

Etiquetas: j2se

Comentarios: 12

  • elisa44 30/01/2007 00:00

    Me he portado muy floja ya que nunca me doy el tiempo para hacer un comentario, siempre busco información en Internet y sólo aquí he encontrado lo que necesito, realmente es excelente, sobre todo los artículos, claros y precisos.
    Muchas gracias

  • v60gsm 14/05/2007 00:00

    Muy Buena Esa Explicaciòn , Debes Ser Profesor

  • CamiloCorrea 29/05/2007 00:00

    Muy buena la explicación, pero no olviden que es importante cerrar los recursos.


    try {
    fos = new FileOutputStream("fichero.bin");
    out = new ObjectOutputStream(fos);
    out.writeObject(o1);
    } catch (FileNotFoundException e) {
    //--->Manejo de la exception
    } catch (IOException e) {
    //--->Manejo de la exception
    }finally{
    if(out!=null){
    try {
    out.close();
    } catch (IOException e1) {
    e1.printStackTrace();
    }
    }
    if(fos!=null){
    try {
    fos.close();
    } catch (IOException e1) {
    e1.printStackTrace();
    }
    }
    }

  • Anónimo 12/11/2007 23:00

    C:Abrir.java:11: unreported exception java.lang.ClassNotFoundException; must be caught or declared to be thrown
    o1=(tablero)in.readObject();
    ^
    1 error

    Process completed.

    esto me pasa :S

  • Anónimo 23/01/2008 15:23

    Cuando creo el fichero me crea el nombre del fichero con números es decir si la pageName es primera me crea algo como primera2323.txt a qué es debido?

     

    File ficVectorOut = File.createTempFile(pageId.trim(),".txt");

     

    Gracias

  • Anónimo 01/05/2008 00:41

    Hola que tal....soy de mexico,,,me gustaria que me mandaran Tips de Java a mi correo...

    por cierto me parece que el lenguaje Java es muy interesante y muy eficaz...a mi parecer es el mejor lenguaje de programacion que existe......

    Quisiera que tomaran en cuenta este comentario y peticion...atentamente Tavo..mi correo es: grchsm11@hotmail.com

  • Anónimo 01/05/2008 00:42

    Hola que tal....soy de mexico,,,me gustaria que me mandaran Tips de Java a mi correo...

    por cierto me parece que el lenguaje Java es muy interesante y muy eficaz...a mi parecer es el mejor lenguaje de programacion que existe......

    Quisiera que tomaran en cuenta este comentario y peticion...atentamente Tavo..mi correo es: grchsm11@hotmail.com

  • Anónimo 16/05/2008 23:49

    hola soy de colombia estoy empesando a trabajar con java y me gustaria que me mandaran consejo de progaramar en java ya  que es un lenguaje de programacion muy interesante y me gustaria conocer mas de el ......

    sy me quieren ayudar favor en viar a my correo to do lo  necesario para programar en java

    este es my correo "cirlyb93@hotmail.com".....

  • Anónimo 14/08/2008 03:45

    AAA MI MSN ES felipecolque@hotmail.com

    soy el del post anterior, agreenme a msn el que e quiera ayuidra porfavor

  • Anónimo 14/08/2008 03:47

    public class Persona {
        private Persona next;
        private String rut;
        private String nombre;
        private int sueldo;
        public Persona(String r, String n,Persona p){
            rut=r;
            nombre=n;
            sueldo=0;
            next=p;
        }
        public Persona(String r){
            rut=r;
        }
        public Persona getPersona(){
            return next;
        }
        public String getRut(){
            return rut;
        }
        public void setRut(String r){
            rut=r;
        }
        public void setPersona(Persona n){
            next=n;
        }
        public void setSueldo(int s){
            sueldo=sueldo+s;
        }
        public void borrarSueldo(int s){
            sueldo=sueldo-s;
       
        }
        public int getSueldo(){
            return sueldo;
        }
        public String getNombre(){
            return nombre;
        }
        public void setNombre(String n){
            nombre=n;
        }
    }   

    public class BaseDato{
        Persona head,actual;
        int suma;
        public BaseDato(){
            head=new Persona("no name"," no rut", null);
            
            suma=0;
        }
        public void agregarPersona(String r,String n){
            Persona aux=head;
            while(aux.getPersona()!=null){
                aux=aux.getPersona();
            }
        
            aux.setPersona(new Persona(r,n,null));
        
        }
        public void agregarSueldo(int s,String r){
            Persona aux=head;
            while(aux.getPersona()!=null){
                if(aux.getPersona().getRut().equals(r)){
                    suma=suma+s;
                    aux.getPersona().setSueldo(s);
                }
                aux=aux.getPersona();
            }
        }
        public boolean borrarPersona(String r){
            Persona aux=head;
            while (aux.getPersona()!=null){
                if(aux.getPersona().getRut().equals(r)){
                    suma=suma-aux.getPersona().getSueldo();
                    aux.setPersona(aux.getPersona().getPersona());
                    return true;
                }
                aux=aux.getPersona();
            }
            return false;
        }
        public int dineroFamiliar(){
            return suma;
        }
        public void abonoFamiliar(int s){
            suma=suma+s;
            
        }
        public boolean realizarGiro(int s,String r){
            Persona aux=head;
            while(aux.getPersona()!=null){
                if(aux.getPersona().getRut().equals(r)){
                    if(aux.getPersona().getSueldo()>s){
                        aux.getPersona().borrarSueldo(s);
                        suma=suma-s;
                        return true;
                    }
                }
                aux=aux.getPersona();
            }
            return false;
        }
        public int consultarSaldo(String r){
            Persona aux=head;
            while(aux.getPersona()!=null){
                if(aux.getPersona().getRut().equals(r)){
                    return aux.getPersona().getSueldo();
                }
                aux=aux.getPersona();
            }
            return 0;
        }
        public boolean verificarRut(String r){
            Persona aux=head;
            while(aux.getPersona()!=null){
                if(aux.getPersona().getRut().equals(r)){
                    return true;
                }
                aux=aux.getPersona();
            }
            return false;
        }
    }

    import java.io.*;
    public class Banco {
        public static void main(String[] args)throws IOException {
            

            BufferedReader op = new BufferedReader(new InputStreamReader(System.in));
             int opcion, cantidad;
             BaseDato base= new BaseDato();
             boolean continuar=true;
             boolean resp;
             String rutt, nombree;
             System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
             System.out.println("                                          Bienvenido al Banco Familiar                                                          ");
             System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
             while(continuar){
                 System.out.println("______________________________________________________________________________________________________________________________");
                 System.out.println("                                  Que opcion desea realizar                                                                   ");
                 System.out.println("  ");
                 System.out.println("1.-Depositar 2.-Girar 3.-Cons. Saldo 4.Agregar cuenta 5. Eliminar Cuenta 6.Conocer sueldo familiar 7.abonar a familia 8.salir");
                 System.out.println("  ");
                 System.out.println("______________________________________________________________________________________________________________________________");
                 opcion=Integer.parseInt(op.readLine());
                 switch(opcion){
                     case 1:
                         System.out.println("Ingrese rut del titular de la cuenta ");
                         rutt=op.readLine();
                        resp=base.verificarRut(rutt);
                        if(resp==false){
                            System.out.println("el rut ingresado no existe, gracias por ingresar a nuestro sistema");
                            System.out.println("   ");
                            break;
                        }
                        System.out.println("el rut ingresado es correcto");
                        System.out.println("   ");
                        System.out.println("Ingrese la cantidad a depositar");
                        cantidad= Integer.parseInt( op.readLine() );
                        base.agregarSueldo(cantidad,rutt);
                        System.out.println("el sueldo ha sido ingresado con exito");
                        System.out.println(" ");
                        break;
                     case 2:
                         System.out.println("Ingrese rut del titular de la cuenta ");
                         rutt=op.readLine();
                         resp=base.verificarRut(rutt);
                        if(resp==false){
                            System.out.println("el rut ingresado no existe, gracias por ingresar a nuestro sistema");
                            System.out.println("   ");
                            break;
                        }
                        System.out.println("el rut ingresado es correcto");
                        System.out.println("   ");
                         
                         System.out.println("Ingrese la cantidad a girar");
                         cantidad= Integer.parseInt( op.readLine() );
                        resp=base.realizarGiro(cantidad,rutt);
                        if(resp==true){
                            System.out.println("   ");
                            System.out.println("el giro ha sido realizado con exito");
                            System.out.println("   ");
                            break;
                        }
                        else{
                            System.out.println(" operacion incorrecta, el monto a girar es mayor al de su cuenta");
                            break;
                        }
                    case 3:
                         System.out.println("Ingrese rut del titular de la cuenta ");
                         rutt=op.readLine();
                         resp=base.verificarRut(rutt);
                        if(resp==false){
                            System.out.println("el rut ingresado no existe, gracias por ingresar a nuestro sistema");
                            System.out.println("   ");
                            break;
                        }
                        System.out.println("el rut ingresado es correcto");
                        System.out.println("   ");
                         System.out.println("saldo:" + base.consultarSaldo(rutt));
                         System.out.println("   ");
                         break;
                      case 4:
                          System.out.println("Ingrese rut del titular de la cuenta ");
                         rutt=op.readLine();
                         System.out.println("   ");
                         System.out.println("Ingrese el nombre de la persona que sera dueña de la cuenta");
                        nombree=op.readLine();
                        base.agregarPersona(rutt,nombree);
                        System.out.println("   ");
                        System.out.println("la cuenta ha sido creada con exito");
                        System.out.println("   ");
                        break;
                      case 5:
                          System.out.println("Ingrese rut del titular de la cuenta a eliminar ");
                         rutt=op.readLine();
                         resp=base.verificarRut(rutt);
                        if(resp==false){
                            System.out.println("   ");
                            System.out.println("el rut ingresado no existe, gracias por ingresar a nuestro sistema");
                            System.out.println("   ");
                            break;
                        }
                        System.out.println("el rut ingresado es correcto");
                        System.out.println("   ");
                         
                         
                         base.borrarPersona(rutt);
                         System.out.println("la cuenta ha sido eliminada con exito ");
                         System.out.println("   ");
                         break;
                         
                     
                     case 6:
                         cantidad=base.dineroFamiliar();
                         System.out.println("   ");
                         System.out.println("la cuenta familiar es de : " + cantidad);
                         System.out.println("   ");
                         break;
                     case 7:
                         System.out.println("   ");
                         System.out.println("Ingrese la cantidad a abonar ");
                         cantidad= Integer.parseInt( op.readLine() );
                         base.abonoFamiliar(cantidad);
                         System.out.println("   ");
                         System.out.println("la operacion ha sido realizada con exito ");
                         System.out.println("   ");
                         break;
                     case 8:
                         continuar=false;
                 }
             }
             System.out.println(" Gracias por  acceder a nuestra sucursal, que tengas un buen dia");
        }
    }

     

    HOLAAAAA LES COMENTO HACE UNOS MESES HE APRENDDO SOBRE JAVA, HE HIZE UAN APPLICACION SENCILLA, SOBRE ALGUN TIPO DE BANCO QUE GUARDA DINERO  , LA COSA ES QUE  EL CODIGO ANTERIOR ES EL DE MI SIMPEL APLICACION, AHORA YO QUIEOR APRENDER COMO DEJAR GUARDADO LSO DATOS QUE VOY  INGRESANDO DE CADA PERSONA PARA QUE PUEDA ULTIZARLOS EN ALGUNA OTRA OCACION CON EL MISMO PROGRAMA, ES DECIR, UAN VEZ CERRADO EL PROGRAMA , QUE EM QUEDEN GUARDADO LSO DATOS Y QUE AL VOLVER A ABRIR LA APLICAICON PUEDA SEGURI UTILIZANDO SO DATOS GUARDADOS, PORFA AYUDENME, SOY PRINCIPIANTE  :)

    felipecolque@hotmail.com

  • Anónimo 10/09/2008 01:04

    Muy bien dia.

    Necesito un Gran favor sobre deserealizacion de archivos, llevo bastante tiempo investigando y no encuentro solucion a mi problema.  Espero que alguien de buena fe me ayude.

    Necesito deserealizar archivos almacenados en mysql server de un tipo de dato longblob, que fueron almacenados por medio de Runa WFE es un entorno de JBoss jBPM motor de flujo de trabajo.

    Yo Serializo Archivos .DOC y Deserealizo solo los  Archivos que yo Serializo (Micodigo), pero no puedo deserealizar los archivos almacenados y Serializados por medio de Runa WFE   

    Me da el siguiente Error:

    java.lang.ClassNotFoundException: ru.runa.wf.FileVariable

    Si alguien me puede ayudar, con resolver este problema, o darme un link donde puedo descargar la clase que necesito, o alguna solucion.

    Mil Gracias.

     Espero su ayuda que tanto la necesito Gracias.

  • Anónimo 01/10/2008 23:02

    necesito saber si alguien puede conectar java a base de datos acces

Escribe tu comentario

Sun Microsystem Logo NHT-Norwick Logo

© 2002-2007 Asociación javaHispano