实现Externalizable
重写writeExtrenal()和readExternal()方法。这两个方法在序列化和反序列化的时候会自动调用。
package com.zachary.io.serializable;
import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
class Blip1 implements Externalizable {
public Blip1(){
System.out.println("Blip1 Constructor");
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
System.out.println("Blip1.writeExternal");
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
System.out.println("Blip1.readExternal");
}
}
class Blip2 implements Externalizable {
Blip2(){
System.out.println("Blip2 constructor");
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
System.out.println("Blip2.writeExternal");
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
System.out.println("Blip2.readExternal");
}
}
/**
* @author Zachary.Zheng
* @version 1.0
* @date 2020年6月3日 下午1:13:43
*/
public class Blips{
public static void main(String[] args) throws Exception {
Blip1 blip1 = new Blip1();
Blip2 blip2 = new Blip2();
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file/output/serializable/Blips.out"));
out.writeObject(blip1);
out.writeObject(blip2);
out.flush();
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("file/output/serializable/Blips.out"));
in.readObject();
// in.readObject(); // 构造函数不是public的会报:java.io.InvalidClassException: com.zachary.io.serializable.Blip2; no valid constructor
in.close();
}
}
Output:
Blip1 Constructor
Blip2 constructor
Blip1.writeExternal
Blip2.writeExternal
Blip1 Constructor
Blip1.readExternal
恢复b1后,会调用Blip1的默认构造器。对于Serializable对象完全由它存储的字节序列化数据来构造,Externalizable对象需要调用构造器方法。
Externalizable序列化部分字段
package com.zachary.io.serializable;
import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
/**
* @author Zachary.Zheng
* @version 1.0
* @date 2020年6月3日 下午1:35:49
*/
public class Blip3 implements Externalizable{
private int i;
private String s; // No initialzation
public Blip3() {
System.out.println("Blip3 constructor");
}
public Blip3(int i, String s) {
System.out.println("Blip3(int i, String s) constructor");
this.i = i;
this.s = s;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(i);
out.writeObject(s);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
i = in.readInt();
s = (String) in.readObject();
}
public String toString() {
return s + i;
}
public static void main(String[] args) throws Exception {
Blip3 b3 = new Blip3(47, "A String ");
System.out.println(b3);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file/output/serializable/Blip3.out"));
out.writeObject(b3);
out.flush();
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("file/output/serializable/Blip3.out"));
b3 = (Blip3) in.readObject();
System.out.println(b3);
in.close();
}
}
Output:
Blip3(int i, String s) constructor
A String 47
Blip3 constructor
A String 47
transient(瞬时)关键字
不想被序列化的敏感数据,使用关键字transient修饰后值不会被序列化。
package com.zachary.io.serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
/**
* @author Zachary.Zheng
* @version 1.0
* @date 2020年6月3日 下午1:59:18
*/
public class Logon implements Serializable {
private static final long serialVersionUID = 1L;
private Date date = new Date();
private String name;
private transient String password;
public Logon(String name, String password) {
super();
this.name = name;
this.password = password;
}
@Override
public String toString() {
return "Logon [date=" + date + ", name=" + name + ", password=" + password + "]";
}
public static void main(String[] args) throws Exception {
Logon a = new Logon("Hulk", "myLittlePony");
System.out.println("Logon a = " + a);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file/output/serializable/Logon.out"));
out.writeObject(a);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("file/output/serializable/Logon.out"));
a = (Logon) in.readObject();
System.out.println("Logon a = " + a);
in.close();
}
}
Output:
Logon a = Logon [date=Wed Jun 03 16:38:25 CST 2020, name=Hulk, password=myLittlePony]
Logon a = Logon [date=Wed Jun 03 16:38:25 CST 2020, name=Hulk, password=null]
Externalizable的替代方法
实现Serializable接口,添加writeObject()和readObject()方法。在序列化和反序列化时会自动分别调用这两个方法。
- defaultWriteObject()和defaultReadObject()方法会执行默认的序列化。
- transient部分使用writeObject()和readObject()序列化。
package com.zachary.io.serializable;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* @author Zachary.Zheng
* @version 1.0
* @date 2020年6月3日 下午2:21:05
*/
public class SerialCtl implements Serializable {
private static final long serialVersionUID = 1L;
private String a;
private transient String b;
public SerialCtl(String a, String b) {
super();
this.a = "No transient" + a;
this.b = "Transient" + b;
}
@Override
public String toString() {
return "SerialCtl [a=" + a + ", b=" + b + "]";
}
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(b);
}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
b = (String) stream.readObject();
}
public static void main(String[] args) throws Exception {
SerialCtl sc = new SerialCtl("Test1", "Test2");
System.out.println("Before\n" + sc);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(buf);
out.writeObject(sc);
out.close();
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()));
sc = (SerialCtl) in.readObject();
System.out.println("After\n" + sc);
in.close();
}
}
Output:
Before
SerialCtl [a=No transientTest1, b=TransientTest2]
After
SerialCtl [a=No transientTest1, b=TransientTest2]