java io流之序列化流和反序列化流
1.简略介绍一下
序列化流 ObjectOutputStream 对象写入文本文件或在网络中传输
反序列化流 ObjectInputStream 文本中的流对象或者网络中的流对象还原为对象
在这里我们让被序列化和反序列化的对象所属的类实现了Serializable接口,在这里需要注意的是Serializable接口是无方法的标记接 口,Serializable的源码如下图所示,since JDK1.1.
2.被序列化和反序列化的对象所属的类。注意serialVersionUID = 1L;// 版本号和transient关键字:serialVersionUID相当于标记序列化对象的关键字,是用来验证版本一致性的;transient可以让对象的成员变量不被序列化,反序列化时获取到的是默认值。
package ObjectStream;
import java.io.Serializable;
/**
* Serializable 无方法 是一个标记接口
* @author feige
*/
public class Person implements Serializable {
private static final long serialVersionUID = 1L;// 版本号
private String name;
private transient int age;// transient可以让对象的成员变量不被实例化,反序列化时取到的是默认值
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
实现序列化和反序列化
package ObjectStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
*序列化流 ObjectOutputStream 对象写入文本文件或在网络中传输
*反序列化流 ObjectInputStream 文本中的流对象或者网络中的流对象还原为对象
* @author feige
*/
public class ObjectStreamDemo {
public static void main(String[] args) throws FileNotFoundException,
IOException, ClassNotFoundException {
Person p = new Person("arui", 25);
write(p);// 序列化
System.out.println("反序列化的结果:"+read());// 反序列化
}
// 序列化
private static void write(Object o) throws FileNotFoundException,
IOException {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(
"serializable"));
os.writeObject(o);
System.out.println("成功序列化一个对象");
os.close();
}
// 反序列化
private static Object read() throws FileNotFoundException, IOException,
ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
"serializable"));
Object o=ois.readObject();
ois.close();
return o;
}
}
结果:
可以看到被transient修饰的age成员变量获取到的是默认值。
3. 不用serialVersionUID引起的异常
Person类注释了serialVersionUID
package ObjectStream;
import java.io.Serializable;
/**
* Serializable 无方法 是一个标记接口
* @author feige
*/
public class Person implements Serializable {
//private static final long serialVersionUID = 1L;// 版本号
private String name;
private transient int age;// transient可以让对象的成员变量不被实例化,反序列化时取到的是默认值
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person() {
super();
}
}
将一个Person类的对象序列化写到一个名为Person的文件
// 序列化
private static void write(Object o) throws FileNotFoundException,
IOException {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(
new File("Person")));
os.writeObject(o);
System.out.println("成功序列化一个对象");
os.close();
}
将Person进行修改,增加了一个新方法addNewMethod
package ObjectStream;
import java.io.Serializable;
/**
* Serializable 无方法 是一个标记接口
* @author feige
*/
public class Person implements Serializable {
//private static final long serialVersionUID = 1L;// 版本号
private String name;
private transient int age;// transient可以让对象的成员变量不被实例化,反序列化时取到的是默认值
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person() {
super();
}
public void addNewMethod(){}
}
这时将Person文件反序列化就会抛出异常
// 反序列化
private static Object read() throws FileNotFoundException, IOException,
ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
new File("Person")));
Object o=ois.readObject();
ois.close();
return o;
}
异常:
这是由于我们没有指定Person类的序列化的版本号,导致改动前后编译器为Person类生成了2个不一样的版本号,所以抛出异常。为此serialVersionUID用来保证版本的一致性。