“序列化”是一种把对象的状态转化成字节流的机制,“反序列”是其相反的过程,把序列化成的字节流用来在内存中重新创建一个实际的Java对象。这个机制被用来“持久化”对象。通过对象序列化,可以方便的实现对象的持久化储存以及在网络上的传输。
对象序列化流:ObjectOutputStream;
由帮助文档知道ObjectOutputStream将原石数据类型和图形写入OutputStream;可读取或重构对象
对象需要实现Serializable接口才能写入流中
writeObject(Object obj)方法可将指定对象写入ObjectOutputStream.
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
public static void main(String[] args) throws IOException {
ObjectOutputStream foo=new ObjectOutputStream(new FileOutputStream("D:/666/He.java"));
Goods s=new Goods("kele",10000);
foo.writeObject(s);
foo.close();
}
}
public class Goods {
private String name;
private int price;
public Goods() {
}
public Goods(String name,int price)
{this.name=name;
this.price=price;}
public String getName() {
return name;}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
运行会报错:
Exception in thread "main" java.io.NotSerializableException: Goods
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at Main.main(Main.java:12)
上面Goods没有实现Serializable接口;所以会报错;使之implements Serializable;但Serializable接口里不含任何抽象方法,所以它不需要重写方法
运行后文件内容变为: sr Goods钑姍nI I priceL namet Ljava/lang/String;xp 't kele 显然除了一些字符外我们无法识别此对象
当然,与其他流一样,一旦打开就不要忘记关闭!!!!!!!
对象反序列化流:ObjectInputStream:
它可反序列化之前使用ObjectOutputStream编写的原始数据和对象。
import java.io.*;
// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
public static void main(String[]args) throws IOException, ClassNotFoundException {
ObjectInputStream fis=new ObjectInputStream(new FileInputStream("D:/666/He.java"));
Object obj=fis.readObject();
Goods s=(Goods)obj;
System.out.println(s.getName()+" "+s.getPrice());
fis.close();
}}
得到了对象中的属性;输出了可乐和它的价格。
用对象序列化流序列化了一个对象后如果修改了对象所属类文件,
import java.io.*;
// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
public static void main(String[]args) throws IOException, ClassNotFoundException
{write();
read();
}
public static void write()throws IOException {
ObjectOutputStream foo=new ObjectOutputStream(new FileOutputStream("D:/666/He.java"));
Goods s=new Goods("kele",10000);
foo.writeObject(s);
foo.close();}
public static void read() throws IOException, ClassNotFoundException {
ObjectInputStream fis=new ObjectInputStream(new FileInputStream("D:/666/He.java"));
Object obj=fis.readObject();
Goods s=(Goods)obj;
System.out.println(s.getName()+" "+s.getPrice());
fis.close();
}
}
import java.io.Serializable;
public class Goods implements Serializable {
private String name;
private int price;
public Goods() {
}
public Goods(String name,int price)
{this.name=name;
this.price=price;}
public String getName() {
return name;}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
如代码所示,先注释掉read方法,用write写入对象,然后重写Goods中的toString方法,再用read读取文件会报出错误
Exception in thread "main" java.io.InvalidClassException: Goods; local class incompatible: stream classdesc serialVersionUID = -1687161514635671270, local class serialVersionUID = 789728371662175168
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2028)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1875)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2209)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1692)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:508)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:466)
at Main.read(Main.java:18)
at Main.main(Main.java:8)
修改类文件会导致serialVersionUID改变;会报错;如需除去此异常,必须在Good类中显示定义serialVersionUID的值;加上private static final long serialVersionUID=41l;即可。
如果不想某个成员变量值被序列化;加上关键字transient即可。