序列化首先解释两个概念:什么是序列化,什么又是反序列化
序列化:将对象转化成留的过程称为序列化。
反序列化:将流转化成对象的过程称之为反序列化。
Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来,重新构造一个相同的对象。这种机制允许你将对象通过网络进行传播,并可以随时把对象持久化到数据库、文件等系统里。Java的序列化机制是RMI、EJB等技术的技术基础。
序列化的用途:
1.利用对象的序列化实现保存应用程序的当前工作状态,下次再启动的时候将自动地恢复到上次执行的状态。
2.解决在对对象流进行读写操作时所引发的问题。
序列化的特点:
1.如果某个类能够被序列化,其子类也可以被序列化。如果该类有父类,则分两种情况来考虑,如果该父类已经实现了可序列化接口。则其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可序列化接口,则该类的父类所有的字段属性将不会序列化。
2.声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态, transient代表对象的临时数据。
3.相关的类和接口:在java.io包中提供的涉及对象的序列化的类与接口有ObjectOutput接口、ObjectOutputStream类、ObjectInput接口、ObjectInputStream类。
Demo
这是一个基础类User
package com.test;
import java.io.Serializable;
public class User implements Serializable {
private int userId;
private String userName;
private String userSex;
private int userAge;
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
@Override
public String toString() {
return this.getUserId() + " " + this.getUserName() + " "
+ this.getUserSex() + " " + this.getUserAge();
}
}
package com.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Test {
/**
*将对象序列化到磁盘文件中
*/
public static void writeObject(Object o) throws Exception{
File f = new File("f:\\user.tmp");
if(f.exists()){
f.delete();
}
FileOutputStream os = new FileOutputStream(f);
//ObjectOutputStream 核心类
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(o);
oos.close();
os.close();
}
/**
*反序列化,将磁盘文件转化为对象
*/
public static User readObject(File f) throws Exception{
InputStream is = new FileInputStream(f);
//ObjectOutputStream 核心类
ObjectInputStream ois = new ObjectInputStream(is);
return (User)ois.readObject();
}
public static void main(String[] args) throws Exception{
/*****************将对象序列化***************/
User user = new User();
user.setUserId(1);
user.setUserName("张艺谋");
user.setUserSex("男");
user.setUserAge(50);
Test.writeObject(user);
/*****************将对象序反列化***************/
User user2 = Test.readObject(new File("f:\\user.tmp"));
System.out.println(user2);
}
}
输出:
这是user.tmp里的内容:
以上我们先将User对象序列化输出到文件中,后将文件中的流反序列化生成一个对象实例,在这里:
(1)ObjectOutput接口:它继承DataOutput接口并且支持对象的序列化,其内的writeObject()方法实现存储一 个对象。
(2)ObjectInput接口:它继承DataInput接口并且支持对象的序列化,其内的readObject()方法实现读取一个对象。
(3)ObjectOutputStream类:它继承OutputStream类并且实现ObjectOutput接口。利用该类来实现将对象存储
(调用ObjectOutput接口中的writeObject()方法)。
(4)ObjectInputStream类:它继承InputStream类并且实现ObjectInput接口。利用该类来实现读取一个对象(调用
ObjectInput接口中的readObject()方法)。
注意:
如果出现父类,对父类的处理:
如果父类没有实现序列化接口,则其必须有默认的构造函数(即没有参数的构造函数)。否则编译的时候就会报错。在反序列化的时候,默认构造函数会被调用。但是若把父类标记为可以序列化,则在反序列化的时候,其默认构造函数不会被调用。这是为什么呢?这是因为Java
对序列化的对象进行反序列化的时候,直接从流里获取其对象数据来生成一个对象实例,而不是通过其构造函数来完成。
以上的内容比较浅显,笔者用到的和JAVA序列化有关的技术不多,如有问题,欢迎大家指出!