Serializable java序列化

Bean Serializable Interface 的接口让BEAN可以串行化,将其变成一个可保存为以后使用的二进制流。当一个BEAN被系列化到磁盘上或者其他任何地方,其状态被保存起来,其中的属性值也不会改变。在BEAN的规范中,JSP并没有要求BEAN实现Serializable接口。但是,如果您希望自己控制您所创建的组件的serialization进程,或者您想serialize并不是标准组件扩展的组件,您必须了解serialization and deserialization的细节。

  有几个原因你会把BEAN冷藏起来以备后用。有些服务器通过将所有的SESSION 数据(包括BEAN)写入磁盘来支持任意长的SESSION生命期,即使服务器停机也不会丢失。当服务器重新启动后,串行化的数据被恢复。同样的理由,在重负载的站点上支持服务器分簇的环境中,许多服务器通过串行化来复制SESSION。如果你的BEAN不支持串行化,服务器就不能正确地保存和传输类。

  通过同样的策略,你可以选择将BEAN保存在磁盘上或者数据库中,以备后用。例如,也许可以将客户的购物车实现为一个BEAN,在访问期间将其保存在数据库中。

  如果BEAN需要特殊的复杂的初始设置,可以将BEAN设置好后串行化保存在磁盘上。这个BEAN的“快照”可以用在任何需要的地方,包括在$#@60;jsp:useBean$#@62;中用beanName属性的调用。

  $#@60;jsp:useBean$#@62;标签中的beanName属性,用来实例化一个串行化的BEAN,而不是用来从一个类创建一个全新的实例。如果BEAN还没有创建,beanName属性传给java.beans.Bean.instantiate()方法,由类装载器对类进行实例化。它首先假定存在一个串行化的BEAN(带有扩展名.ser),然后会将其激活。如果这个操作失败,它就会实例化一个新的实例。
  下面简单介绍一下这个接口:

  对象能包含其它的对象,而这其它的对象又可以包含另外的对象。JAVA serialization能够自动的处理嵌套的对象。对于一个对象的简单的域,writeObject()直接将值写入流。而,当遇到一个对象域时,writeObject()被再次调用,如果这个对象内嵌另一个对象,那么,writeObject() 又被调用,直到对象能被直接写入流为止。程序员所需要做的是将对象传入ObjectOutputStream 的writeObject() 方法,剩下的将又系统自动完成。

一个FileOutputStream对象被创建且传到一个ObjectOutputStream。当out.writeObject() 被调用,这个串和mine 对象被objects are serializ顺序加入一个存入文件PersonalData.ser的字节对列。

  您应该注意上述类是实现的java.io.Serializable接口。因为它并未指定要实现的方法,所以Serializable被称为"tagging interface" ,但是它仅仅"tags"它自己的对象是一个特殊的类型。任一个您希望serialize的对象都应该实现这个接口。这是必须的。否则,用到流技术时将根本不工作。例如,如果您试着去serialize 一个没有实现这个接口的对象,一个 NotSerializableException将产生。

 

类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。

  Java的"对象序列化"能让你将一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象时候,你就能把这些byte数据恢复出来,并据此重新构建那个对象了。

  要想序列化对象,你必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream。这时,你就能用writeObject( )方法把对象写入OutputStream了。

  writeObject 方法负责写入特定类的对象的状态,以便相应的 readObject 方法可以还原它。通过调用 out.defaultWriteObject 可以调用保存 Object 的字段的默认机制。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。

  读的时候,你得把InputStream嵌到ObjectInputStream里面,然后再调用readObject( )方法。不过这样读出来的,只是一个Object的reference,因此在用之前,还得先下传。readObject 方法负责从流中读取并还原类字段。它可以调用 in.defaultReadObject 来调用默认机制,以还原对象的非静态和非瞬态字段。

   defaultReadObject 方法使用流中的信息来分配流中通过当前对象中相应命名字段保存的对象的字段。这用于处理类发展后需要添加新字段的情形。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class PersonData implements Serializable {
	public int id = 101;
	public int yearOfBirth=1987;
	public float yearOfSalary = 46500.00F;
}
public class TestSerial {
	public static void main(String[] args) {
		try {
			FileOutputStream fos = new FileOutputStream("temp.txt");
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			PersonData pd = new PersonData();
			oos.writeObject("My person data");
			oos.writeObject(pd);
			oos.flush();
			oos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch(IOException e ) {
			e.printStackTrace();
		}
		try {
			FileInputStream fis = new FileInputStream("temp.txt");
			ObjectInputStream ois = new ObjectInputStream(fis);
			String str = (String)ois.readObject();
			PersonData pd = (PersonData)ois.readObject();
			System.out.println(str);
			System.out.print(pd.id+","+pd.yearOfBirth+","+pd.yearOfSalary);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch(IOException e) {
			e.printStackTrace();
		}catch(ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		
	}
}
输出:My person data
101,1987,46500.0

在序列化时,有几点要注意的:
  1:当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。
  2:如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
  3:如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化
  还有我们对某个对象进行序列化时候,往往对整个对象全部序列化了,比如说类里有些数据比较敏感,不希望序列化,一个方法可以用transient来标识,另一个方法我们可以在类里重写方法

private   void  readObject(java.io.ObjectInputStream stream)
     
 throws 
 IOException, ClassNotFoundException;
 
 private   void 
 writeObject(java.io.ObjectOutputStream stream)
     
 throws 
 IOException

例:

import  java.io. * ;

 class  ObjectSerialTest
 {
     public   static   void  main(String[] args)  throws  Exception
     {
        Employee e1 = new  Employee( " zhangsan " , 25 , 3000.50 );
        Employee e2 = new  Employee( " lisi " , 24 , 3200.40 );
        Employee e3 = new  Employee( " wangwu " , 27 , 3800.55 );
        
        FileOutputStream fos = new  FileOutputStream( " employee.txt " );
        ObjectOutputStream oos = new  ObjectOutputStream(fos);
        oos.writeObject(e1);
        oos.writeObject(e2);
        oos.writeObject(e3);
        oos.close();
        
        FileInputStream fis = new  FileInputStream( " employee.txt " );
        ObjectInputStream ois = new  ObjectInputStream(fis);
        Employee e;
         for ( int  i = 0 ;i < 3 ;i ++ )
         {
            e = (Employee)ois.readObject();
            System.out.println(e.name + " : " + e.age + " : " + e.salary);
        } 
        ois.close();
    } 
} 
 
 class  Employee  implements  Serializable
 {
    String name;
     int  age;
     double  salary;
     transient  Thread t = new  Thread();
     public  Employee(String name, int  age, double  salary)
     {
         this .name = name;
         this .age = age;
         this .salary = salary;
    } 
     private   void  writeObject(java.io.ObjectOutputStream oos)  throws  IOException
     {
        oos.writeInt(age);
        oos.writeUTF(name);
        System.out.println( " Write Object " );
    } 
     private   void  readObject(java.io.ObjectInputStream ois)  throws  IOException
     {
        age = ois.readInt();
        name = ois.readUTF();
        System.out.println( " Read Object " );
    } 
 
}


你可能感兴趣的:(java,bean,String,object,serialization,服务器)