0x01 前言
在Java中实现对象反序列化非常简单
只需要继承并实现 java.io.Serializable
或是 java.io.Externalizable
接口即可被序列化
其中 java.io.Externalizable
只是实现了 java.io.Serializable
的接口
但是两者还是有区别的,区别如下:
注意: 复制了P牛的小圈子一个大佬发的结论,比我自己总结的更好, 总的来说,有点小小修改
- 实现
Externalizable
, 序列化过程需要开发人员自己实现。未实现writeExternal()
和readExternal()
,则序列化时不会保存和读取任何字段。属性使用和不使用 transient 修饰,无任何区别 Externalizable
优先级比Serializable
更高- 如果在序列化的时候使用了构造方法的情况下,那
Externalizable
必须要创建默认的无参构造方法,Serializable
方法可以没有默认的无参构造方法
其中第三点,需要在在在注意一下,使用 Externalizable 的时候:
如果你在序列化的时候没有使用构造方法!!!!!
那么是可以不创建无参构造方法也能成功反序列化的
但是如果你使用了构造方法来进行序列化!!!!!
那么则必须创建一个无参构造方法,这样才能成功的反序列化
0x02 类方法讲解
Externalizable 类主要有两个方法
writeExternal() # 类被序列化时调用
readExternal() # 类被反序列化时调用
0x03 例子
0x03.1 无构造方法例子
0x03.1.1 writeExternal()
// 第一步创建 ExternalizableTest1 类
package java反序列化测试;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class ExternalizableTest1 implements Externalizable {
public String test1;
public transient String test2;
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject("1111");
out.writeObject("2222");
System.out.println("writeExternal.......");
}
@Override
public void readExternal(ObjectInput in) {
}
}
// 第二步-序列化 ExternalizableTest1 类
package java反序列化测试;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeDemo4 {
public static void main(String[] args) {
// ExternalizableTest1 序列化
ExternalizableTest1 e = new ExternalizableTest1();
try {
FileOutputStream fileOut = new FileOutputStream("./src/main/java/java反序列化测试/ExternalizableTest1.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
} catch (IOException i) {
i.printStackTrace();
}
}
}
// 运行结果:
// 输出: writeExternal.......
// 并且会在在 /src/main/java/java反序列化测试/ 生成一个 ExternalizableTest1.ser 文件
0x03.1.2 readExternal()
// 第一步创建 ExternalizableTest2 类
package java反序列化测试;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class ExternalizableTest2 implements Externalizable {
public String test1;
public transient String test2;
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject("1111");
out.writeObject("2222");
System.out.println("writeExternal.......");
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.test1 = (String) in.readObject();
this.test2 = (String) in.readObject();
System.out.println("readExternal.......");
}
}
// 第二步-序列化 ExternalizableTest2 类
package java反序列化测试;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeDemo5 {
public static void main(String[] args) {
// ExternalizableTest2 序列化
ExternalizableTest2 e = new ExternalizableTest2();
try {
FileOutputStream fileOut = new FileOutputStream("./src/main/java/java反序列化测试/ExternalizableTest2.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
} catch (IOException i) {
i.printStackTrace();
}
}
}
// 运行结果:
// 输出: writeExternal.......
// 并且会在在 /src/main/java/java反序列化测试/ 生成一个 ExternalizableTest2.ser 文件
// 第三步-反序列化 ExternalizableTest2 类
package java反序列化测试;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserializationDemo5 {
public static void main(String[] args) {
// 反序列化 ExternalizableTest2
try {
FileInputStream fileIn = new FileInputStream("./src/main/java/java反序列化测试/ExternalizableTest2.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
ExternalizableTest2 e = (ExternalizableTest2) in.readObject();
in.close();
fileIn.close();
System.out.println(e.test1);
System.out.println(e.test2);
} catch (IOException i) {
i.printStackTrace();
return;
} catch (ClassNotFoundException c) {
System.out.println("ExternalizableTest2 class not found");
c.printStackTrace();
return;
}
}
}
// 运行结果:
// 输出:
// readExternal() 被调用输出 readExternal.......
// e.test1 被打印输出 1111
// e.test2 被打印输出 2222
0x03.2 有构造方法例子
0x03.2.1 writeExternal()
// 第一步创建 ExternalizableTest3 类
package java反序列化测试;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class ExternalizableTest3 implements Externalizable {
public String test1;
public transient String test2;
public ExternalizableTest3() {
}
public ExternalizableTest3(String test1, String test2) {
super();
this.test1 = test1;
this.test2 = test2;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.test1);
out.writeObject(this.test2);
System.out.println("writeExternal.......");
}
@Override
public void readExternal(ObjectInput in) {
}
}
// 第二步-序列化 ExternalizableTest3 类
package java反序列化测试;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeDemo6 {
public static void main(String[] args) {
// ExternalizableTest3 序列化
ExternalizableTest3 e = new ExternalizableTest3("test11", "test22");
try {
FileOutputStream fileOut = new FileOutputStream("./src/main/java/java反序列化测试/ExternalizableTest3.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
} catch (IOException i) {
i.printStackTrace();
}
}
}
// 运行结果:
// 输出: writeExternal.......
// 并且会在在 /src/main/java/java反序列化测试/ 生成一个 ExternalizableTest3.ser 文件
0x03.2.2 readExternal()
// 第一步创建 ExternalizableTest4 类
package java反序列化测试;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class ExternalizableTest4 implements Externalizable {
public String test1;
public transient String test2;
public ExternalizableTest4() {
}
public ExternalizableTest4(String test1, String test2) {
super();
this.test1 = test1;
this.test2 = test2;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.test1);
out.writeObject(this.test2);
System.out.println("writeExternal.......");
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.test1 = (String) in.readObject();
this.test2 = (String) in.readObject();
System.out.println("readExternal.......");
}
}
// 第二步-序列化 ExternalizableTest4 类
package java反序列化测试;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeDemo7 {
public static void main(String[] args) {
// ExternalizableTest4 序列化
ExternalizableTest4 e = new ExternalizableTest4("test11", "test22");
try {
FileOutputStream fileOut = new FileOutputStream("./src/main/java/java反序列化测试/ExternalizableTest4.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
} catch (IOException i) {
i.printStackTrace();
}
}
}
// 运行结果:
// 输出: writeExternal.......
// 并且会在在 /src/main/java/java反序列化测试/ 生成一个 ExternalizableTest4.ser 文件
// 第三步-反序列化 ExternalizableTest4 类
package java反序列化测试;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserializationDemo6 {
public static void main(String[] args) {
// 反序列化 ExternalizableTest4
try {
FileInputStream fileIn = new FileInputStream("./src/main/java/java反序列化测试/ExternalizableTest4.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
ExternalizableTest4 e = (ExternalizableTest4) in.readObject();
in.close();
fileIn.close();
System.out.println(e.test1);
System.out.println(e.test2);
} catch (IOException i) {
i.printStackTrace();
return;
} catch (ClassNotFoundException c) {
System.out.println("ExternalizableTest4 class not found");
c.printStackTrace();
return;
}
}
}
// 运行结果:
// 输出:
// readExternal() 被调用输出 readExternal.......
// e.test1 被打印输出 test11
// e.test2 被打印输出 test22