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必定实现了这些方法:
实现的主要思路:
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 IOExceptionvoid 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()写入/读出序列化对象,
writeObject方法的参数类的实例化对象,显然,writeObject方法是将二进制流写入文件中,在此处,Person类和PersonEx类 实现了不同的序列化方法,因此写入的二进制流显然是不同的。
oos.writeObject(new Person("张三",30));
Object per=ois.readObject();
在使用Externalizable接口的类中,需要定义一个无参的构造方法,因为在进行反序列化的时候会使用无参构造方法为其进行反序列化。之后再将属性赋值。
在开发中,使用Serialiable接口是最多的。
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中引入类集的概念,解决数组存储数据的数量限制问题。
转载于:https://blog.51cto.com/4989715/1420083