1、基本概念

首先要说的是,Hibernate中ORM里对应的映射文件BEAN,必须实现序列化.因为BEAN里的数据需要存入数据库(要转化为二进制保存),进行存取工作.
JAVA类的数据 ,如果要进行相关的存储工作(如写文件,网络传输,写数据库等),那么这个数据的类 就必须实现序列化接口 (java.io.Serializable)------用于作为一种将 Java 对象的状态转换为字节数组,以便存储或传输的机制,以后,仍可以将字节数组转换回 Java 对象原有的状态。

序列化 :  把对象转换 为二进制数据(如网络传输,存储数据库等),必须实现序列化接口 (java.io.Serializable).

持久化 :  把对象保存 在介质上(如写文件,读文件不是), 没有接口实现,一般指方法调用. 

如果按照存储介质和生命周期的长短划分,所有的数据都以两种形式存在,

其中一种是保存于内存中的运行时对象;

另一种则是存储于持久化物理介质中的文件,比如数据库文件等。

数据的持久化关注于相同的数据在不同形态数据之间的转化,解决的是如何将内存对象持久化存储,以及从物理介质中加载数据并创建内存对象。

数据的持久化是序列化的又一个典型的应用,对象只有在序列化之后才能进行持久化存储,从持久化存储介质加载的数据通过反序列化转变成运行时对象。

当某个字段被声明为transient后,默认序列化机制就会忽略该字段。

此处将Person类中的age字段声明为transient,如下所示,

public class Person implements Serializable {
   
    transient private Integer age = null;
   
}

再执行SimpleSerial应用程序,会有如下输出:

arg constructor

[John, null, MALE]

1、对象序列化

一个对象的序列化就是在内存上开辟了一个存储空间,方便存储对象;

对象序列化就是把一个对象变为二进制数据流的一种方法。如果一个类的对象想被序列化,则对象所在的类必须实现

java.io.serializable接口。

public interface Serializable():这个接口中没有任何一个方法,此接口属于一个标识接口,没有任何内容;

要完成对象的序列化和反序列化,必须依靠对象输入流ObjectOutputStream和对象输入流ObjectInputStream.

对于不同的JDK版本,序列化和反序列化化存在版本差异问题。因此需要serialVersionUID验证版本一致性。如果使用开发工具开发,则会出现安全警告。

序列化:

public class ObjectOutputStreamextends OutputStreamimplements ObjectOutput, ObjectStreamConstants

反序列化:

public interface ObjectOutputextends DataOutput, AutoCloseable

ObjectOutput接口是DataOutput接口的子接口。而DataOutputStream有一系列的输出方法,因此类Object、outputStream必定实现了这些方法:

wKiom1OIVPvxMaTxAARDzLRc_V0282.jpg

实现的主要思路:

1、用文件输出流和文件输入流初始化OutputStream和InputStream对象;

2、 OutputStream和InputStream实现了DateOutput接口,因此使用 OutputStream和InputStream对象的writeObject()和readObject()方法写入读取对象的值。

public class SerDemo {

 /**

  * @param args

  * @throws IOException

  * @throws ClassNotFoundException

  */

 public static void main(String[] args) throws IOException, ClassNotFoundException {

  // TODO Auto-generated method stub

  File fout=new File("D:"+File.separator+"SerDemo.txt");

  ObjectOutputStream oos=null;

  OutputStream out=new FileOutputStream(fout);//定义文件输出流。

  oos=new ObjectOutputStream(out);

  oos.writeObject(new Person("张三",30));

  oos.close();

  File fin=new File("D:"+File.separator+"SerDemo.txt");

  ObjectInputStream ois=null;

  InputStream in=new FileInputStream(fin);

  ois=new ObjectInputStream(in);

  Object per=ois.readObject();

  ois.close();

  System.out.println(per);

 }

}

2、Externalizable手动序列化

上述的序列化过程是自动实现的,如果要实现手动序列化,必须实现extenalizable接口。该接口定义了两个方法:

public interface Externalizable

extends Serializable

void writeExternal(ObjectOutput out)
                   throws IOException
void readExternal(ObjectInput in)
                  throws IOException,
                         ClassNotFoundException

也就是说,如果一个类实现了Externalizable接口,则必须实现上述两种方法。

public class PersonEx implements Externalizable{

 private String name;

 private int age;

 public String toString(){

  return this.name+this.age;

 }

 public PersonEx(){};

 public PersonEx(String name,int age){

  this.name=name;

  this.age=age;

 }

 //必须实现该接口的方法。 在这里我们可以选择需要被实例化的属性,这也是同Serializable接口的不同之处,但是,由于

//transient关键字的使用,使得Externalizable没有几乎没有用武之地了。

  public void writeExternal(ObjectOutput out) throws IOException{

   out.writeObject(this.name);

   out.writeInt(age);

   

  }

  public void readExternal(ObjectInput in)throws IOException,ClassNotFoundException{

   this.name=(String)in.readObject();

   this.age=in.readInt();

  }

}


在这里我解释一下:PersonEx和Person类的区别在于:同样是使用ObjectOutputStream()/ObjectInputStream()写入/读出序列化对象, 

  oos.writeObject(new Person("张三",30));

  Object per=ois.readObject(); 

writeObject方法的参数类的实例化对象,显然,writeObject方法是将二进制流写入文件中,在此处,Person类和PersonEx类 实现了不同的序列化方法,因此写入的二进制流显然是不同的。

在使用Externalizable接口的类中,需要定义一个无参的构造方法,因为在进行反序列化的时候会使用无参构造方法为其进行反序列化。之后再将属性赋值。

在开发中,使用Serialiable接口是最多的。

wKiom1OIVNawZwC0AACzfCchLBI922.jpg

3、序列化一组对象

    如果要保存一组对象,则最好使用对象数组的形式。

public class SerDemo5 {

 private String name ;

 private int age;

 public String toString(){

  return this.name+this.age;

 }

 public static void main(String[] args) throws IOException, ClassNotFoundException {

  File fout=new File("D:"+File.separator+"SerDemo2.txt");

  ObjectOutputStream oos=null;

  OutputStream out=new FileOutputStream(fout);//定义文件输出流。

  oos=new ObjectOutputStream(out);

  //这句话的意思是向一个文件输出流中写入对象PersonEx。而这个对象是可以被序列化的

  //因为该类实现了Externalizable接口,因此采用该接口中的方法手动完成序列化。

  PersonEx obj[]={new PersonEx("张三",30),new PersonEx("李四",31),new PersonEx("王五",32)};

  oos.writeObject(obj);

  oos.close();

  File fin=new File("D:"+File.separator+"SerDemo2.txt");

  ObjectInputStream ois=null;

  InputStream in=new FileInputStream(fin);

  ois=new ObjectInputStream(in);

  Object per[]=(Object[])ois.readObject();

  ois.close();

  for(int i=0;i<per.length;i++)

   System.out.println(per[i]);

 }

}

通过这种方法可以存储一组对象,但是在java中,数组存储的数量是有限制的,因此java中引入类集的概念,解决数组存储数据的数量限制问题。