一、使用对象流实现序列化。
先定义一个可序列化的对象
package com.shy.IO; import java.io.Serializable; public class Person implements Serializable{ public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } private int age; private String name; public Person(String name , int age){ this.age = age; this.name = name; } }
然后将Persen类的实例使用对象流序列化
package com.shy.IO; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class WriteObject { public static void main(String[] args) { try ( ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("object.txt")); ) { Person person = new Person("yuyu", 22); outputStream.writeObject(person); } catch (IOException ioe) { ioe.printStackTrace(); } } }
最后再反序列化
package com.shy.IO; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class ReadObject { public static void main(String[] args) { try ( ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("object.txt")) ) { Person person = (Person) inputStream.readObject(); System.out.println(person.getName()+"的年龄为"+person.getAge()); } catch (IOException ioe) { ioe.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }finally { } } }
由上面代码可以看出,反序列化时必须进行downcasting,而且反序列化机制度区的仅仅是java对象的数据,而且没有使用对象构造器,这表明反序列化机制无需通过构造起来初始化java对象。
二、java对象序列化算法内容简介
1、所有保存到磁盘中的对象都有一个序列化编号。
2、当程序试图序列化一个对象时,程序会先检查该对象是否被序列化过,只有该对象从未(在本次虚拟机中)被序列化过,系统才会将对象转化为字节序列并输出。
3、如果某个对象已经序列化过,程序将只是直接输出一个序列化编号,而不是再次重新序列化该对象。
三、自定义序列化
对实现了Serializable接口的对象,可使用下列三种方式来自定义序列化与反序列化。
第一种方式,若在实例成员变量前面使用transient关键字修饰,可以指定java序列化时无需理会该实例变量;
第二种方式,在需要序列化的类中提供如下特殊签名的方法,在这些方法中分别对java对象的成员变量用out.writeObject()方法进行存取
private void writeObject(java.io.ObjectOutputStream out)throws IOException; private void readObject(java.io.ObjectInputStream in)throws IOException,ClassNotFoundException; private void readObjectNoData()throws ObjectStreamException;
第三种方式,在序列化时将该对象替换成其他对象,此时应该为序列化提供如下方法,序列化机制会序列化该方法返回的对象。
private Object writeReplace() throws ObjectStreamException;
通过上面介绍,可以知道java序列化机制在将对象序列化写入文件之前,先调用被序列化对象的writeObject方法,然后再调用writeReplace方法,相对应的,在从文件中读取对象时的最后,会调用readObject方法,之后再调用readResolve方法,该方法和writeReplace方法很像,可以将源序列化对象转换为另一个对象来返回,可以用来实现白虎幸福之整个对象。
四、另一种序列化机制,实现Externalizable接口
与serializable这种声明式接口不同,Externalizable接口里面定义了两个方法writeExternal() and readExternal()两个方法,这两个方法除了名字与writeObject和readObject不同外其他都相同,用处就是强制自定义序列化。
五、序列化的范围
对象的类名和实例变量都会被序列化,方法、类变量,transient变量都不会被序列化。
六、serialVersionUID
在定义序列化对象时最好手动定义序列化对象的版本,也就是在序列化对象中定义一个静态成员变量,private static fianl long serialVersionUID = 512L;用于保证class文件改变之后还可以正确反序列化。