1.需求
使用Externalizable实现序列化
2.Externalizable源码
public interface Externalizable extends java.io.Serializable { /** * The object implements the writeExternal method to save its contents * by calling the methods of DataOutput for its primitive values or * calling the writeObject method of ObjectOutput for objects, strings, * and arrays. * * @serialData Overriding methods should use this tag to describe * the data layout of this Externalizable object. * List the sequence of element types and, if possible, * relate the element to a public/protected field and/or * method of this Externalizable class. * * @param out the stream to write the object to * @exception IOException Includes any I/O exceptions that may occur */ void writeExternal(ObjectOutput out) throws IOException; /** * The object implements the readExternal method to restore its * contents by calling the methods of DataInput for primitive * types and readObject for objects, strings and arrays. The * readExternal method must read the values in the same sequence * and with the same types as were written by writeExternal. * * @param in the stream to read data from in order to restore the object * @exception IOException if I/O errors occur * @exception ClassNotFoundException If the class for an object being * restored cannot be found. */ void readExternal(ObjectInput in) throws IOException, ClassNotFoundException; }
首先,我们在序列化对象的时候,由于这个类实现了Externalizable 接口,在writeExternal()方法里定义了哪些属性可以序列化,
哪些不可以序列化,所以,对象在经过这里就把规定能被序列化的序列化保存文件,不能序列化的不处理,然后在反序列的时候自动调用readExternal()方法,根据序列顺序挨个读取进行反序列,并自动封装成对象返回,然后在测试类接收,就完成了反序列
所以说Exterinable的是Serializable的一个扩展
3.举个栗子
需要序列化的类Person
package com.serializable; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.text.SimpleDateFormat; import java.util.Date; public class Person implements Externalizable { private static final long serialVersionUID = 2534579427612174172L; private String name; private Integer age; private transient String gender; public Person() { } public Person(String name, Integer age, String gender) { this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public void writeExternal(ObjectOutput out) throws IOException { Date date=new Date(); out.writeObject(name); out.writeObject(age); out.writeObject(date); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name=(String) in.readObject(); age=(Integer) in.readObject(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); Date date=(Date)in.readObject(); System.out.println("反序列化后的日期为:"+sdf.format(date)); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", gender='" + gender + '\'' + '}'; } }
序列化类
public class Client { /** * 序列化方法 * @throws IOException * @throws FileNotFoundException */ public void serializable(Person person) throws FileNotFoundException, IOException { ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream("temp2")); outputStream.writeObject(person); } /** * 反序列化的方法 * @throws IOException * @throws FileNotFoundException * @throws ClassNotFoundException */ public Person deSerializable() throws FileNotFoundException, IOException, ClassNotFoundException{ ObjectInputStream ois=new ObjectInputStream(new FileInputStream("temp2")); return (Person) ois.readObject(); } @Test public void test() throws Exception { Client client=new Client(); Person person=new Person("村长",20,"man"); System.out.println("为序列化之前的相关数据如下:\n"+person.toString()); client.serializable(person); Person newPerson=client.deSerializable(); System.out.println("-------------------------------------------------------"); System.out.println("序列化之后的相关数据如下:\n"+newPerson.toString()); } }
4.注意
1.java中的序列化时transient变量(这个关键字的作用就是告知JAVA我不可以被序列化)和静态变量不会被序列化
2.也是最应该注意的,如果你先序列化对象A后序列化B,那么在反序列化的时候一定记着JAVA规定先读到的对象 是先被序列化的对象,不要先接收对象B,那样会报错.尤其在使用上面的Externalizable的时候一定要注意读取 的先后顺序
3.实现序列化接口的对象并不强制声明唯一的serialVersionUID,是否声明serialVersionUID对于对象序列化的向 上向下的兼容性有很大的影响