Java 序列化
什么是序列化:
简单来说,序列化就是把对象的属性值写进一个磁盘中(如txt文件)进行保存。而反序列化就是将保存进磁盘的数据读取到程序中。整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。
其中, ObjectInputStream(反序列化) 和 ObjectOutputStream(序列化)是高层次的数据流。
作用及方法:
一个类只要是实现了Serilizable接口,这个类的对象就可以被实例化(包含这个类的所有属性)。但是,根据开发的实际情况,有些需要保密的属性不希望被序列化,那怎么办呢。这个时候就需要transient关键字了。
被transient修饰的属性,在序列化对象的时候,这个属性就不会序列化到指定的目的地中。
例如:Employee类实现接口Serilizable,成为可序列化的类
import java.io.Serializable; public class Employee implements Serializable{ public String name; public String address; public transient int SSN; public int number; public void mailCheck(){ System.out.println("Mailing a check to " + name + " " + address); } }
类SerializeDemo为序列化过程:将类属性的值存进C:/user.txt中。
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class SerializeDemo { public static void main(String [] args) { Employee e = new Employee(); e.name = "Reyan Ali"; e.address = "Phokka Kuan, Ambehta Peer"; e.SSN = 11122333; e.number = 101; try { FileOutputStream fileOut = new FileOutputStream("C:/user.txt"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(e); out.close(); fileOut.close(); System.out.printf("Serialized data is saved in /tmp/employee.ser"); }catch(IOException i) { i.printStackTrace(); } } }
类DeserializeDemo为反序列化过程,将序列化进文件的值取出
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class DeserializeDemo { public static void main(String [] args) { Employee e = null; try { FileInputStream fileIn = new FileInputStream("C:/user.txt"); ObjectInputStream in = new ObjectInputStream(fileIn); e = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println("Employee class not found"); c.printStackTrace(); return; } System.out.println("Deserialized Employee..."); System.out.println("Name: " + e.name); System.out.println("Address: " + e.address); System.out.println("SSN: " + e.SSN); System.out.println("Number: " + e.number); } }
输出结果:因为SSN被transient修饰,所以无法序列化,因而值为0。
Deserialized Employee... Name: Reyan Ali Address: Phokka Kuan, Ambehta Peer SSN: 0 Number: 101
序列化学习要点:
- 被transient修饰的属性无法进行序列化,即其值不能存储进文档中
- 一个静态变量不管是否被transient修饰,均不能被序列化。
- transient关键字只能修饰变量,而不能修饰方法和类
是否被transient修饰的变量就无法序列化了呢?
答案是否定的,被transient修饰的变量在某些特殊的时刻也是可以被序列化的。理由如下:
当要被序列化的类继承的是Serilizable接口,则该类中所属性均可以序列化(除去被transient修饰的变量以外)。
当要被序列化的类继承的是Externalizable接口,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。
例如:Employee为要被序列化的类。
import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; public class Employee implements Externalizable { public String name; public String address; public transient int SSN; public int number; @Override public void readExternal(ObjectInput arg0) throws IOException, ClassNotFoundException { name = (String) arg0.readObject(); SSN = Integer.parseInt(arg0.readObject().toString()); } @Override public void writeExternal(ObjectOutput arg0) throws IOException { arg0.writeObject(name); arg0.writeObject(SSN); } }
类SerializeDemo为序列化过程
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class SerializeDemo { public static void main(String [] args) { Employee e = new Employee(); e.name = "不是山谷"; e.address = "Phokka Kuan, Ambehta Peer"; e.SSN = 11122333; e.number = 101; try { FileOutputStream fileOut = new FileOutputStream("C:/user.txt"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(e); out.close(); fileOut.close(); System.out.printf("Serialized data is saved in /tmp/employee.ser"); }catch(IOException i) { i.printStackTrace(); } } }
类DeserializeDemo为反序列化过程
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class DeserializeDemo { public static void main(String [] args) { Employee e = new Employee(); try { FileInputStream fileIn = new FileInputStream("C:/user.txt"); ObjectInputStream in = new ObjectInputStream(fileIn); e = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println("Employee class not found"); c.printStackTrace(); return; } System.out.println("Deserialized Employee..."); System.out.println("Name: " + e.name); System.out.println("Address: " + e.address); System.out.println("SSN: " + e.SSN); System.out.println("Number: " + e.number); } }
输出结果:
Deserialized Employee... Name: 不是山谷 Address: null SSN: 11122333 Number: 0