为什么需要序列化?
对于一个存在Java虚拟机中的对象来说,其内部的状态只是保存在内存中。JVM退出之后,内存资源也就被释放,Java对象的内部状态也就丢失了。而在很多情况下,对象内部状态是需要被持久化的,将运行中的对象状态保存下来(最直接的方式就是保存到文件系统中),在需要的时候可以还原,即使是在Java虚拟机退出的情况下。
对象序列化机制是Java内建的一种对象持久化方式,可以很容易实现在JVM中的活动对象与字节数组(流)之间进行转换,使用得Java对象可以被存储,可以被网络传输,在网络的一端将对象序列化成字节流,经过网络传输到网络的另一端,可以从字节流重新还原为Java虚拟机中的运行状态中的对象。
对象序列化相关的类与接口
1.Java类中对象的序列化工作是通过ObjectOutputStream和ObjectInputStream来完成的。
序列化对象输出操作必须通过调用:private void writeObject(ObjectOutputStream out)方法实现。这个方法将抛出IOException异常。
反序列化对象输入的操作必须通过调用private void readObject(ObjectInputStream in)方法实现。这个方法将抛出IOException和ClassNotFoundException异常。
2. 对于任何需要被序列化的对象,都必须要实现接口Serializable,它只是一个标识接口,本身没有任何成员,只是用来标识说明当前的实现类的对象可以被序列化。
3. 如果在类中的一些属性,希望在对象序列化过程中不被序列化,使用关键字transient标注修饰就可以。当对象被序列化时,标注为transient的成员属性将会自动跳过。
对象序列化应该注意的一些问题
1.当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法,静态的成员变量和transient标注的成员变量。
2.如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存还原,而且会是递归的方式。
3.如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。可以将这个引用标记transient,那么对象仍然可以序列化。
下面看一个实例:
定义对象,实现Serializable接口
package com.tzy.serializable; import java.io.Serializable; public class Product implements Serializable { private static final long serialVersionUID = 5260133645081293623L; private String ID; private String title; private double price; public Product(String iD, String title, double price) { ID = iD; this.title = title; this.price = price; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getID() { return ID; } }
package com.tzy.serializable; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class WriteObjectDemo { public static void main(String[] args) { Product thinkpadPC = new Product("T110", "thinkpad", 5000); Product idelpadPC = new Product("G110", "idelpad", 4600); String fileName = "C:\\Procuct.dat"; try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName))) { out.writeObject(thinkpadPC); out.writeObject(idelpadPC); } catch (FileNotFoundException e) { System.err.println(e); } catch (IOException e) { System.err.println(e); } System.out.println("Succss!"); } }
package com.tzy.serializable; import java.io.FileInputStream; import java.io.ObjectInputStream; public class ReadObjectDemo { public static void main(String[] args) { Product product1 = null; Product product2 = null; String fileName = "C:\\Procuct.dat"; try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName))) { product1 = (Product) in.readObject(); product2 = (Product) in.readObject(); } catch (Exception e) { System.err.println(e); } System.out.println(product1.getID()); System.out.println(product1.getTitle()); System.out.println(product1.getPrice()); System.out.println(product2.getID()); System.out.println(product2.getTitle()); System.out.println(product2.getPrice()); } }