0x01 前言

在Java中实现对象反序列化非常简单
只需要继承并实现 java.io.Serializable 或是 java.io.Externalizable 接口即可被序列化

其中 java.io.Externalizable 只是实现了 java.io.Serializable 的接口
但是两者还是有区别的,区别如下:
注意: 复制了P牛的小圈子一个大佬发的结论,比我自己总结的更好, 总的来说,有点小小修改

  1. 实现 Externalizable, 序列化过程需要开发人员自己实现。未实现 writeExternal()readExternal(),则序列化时不会保存和读取任何字段。属性使用和不使用 transient 修饰,无任何区别
  2. Externalizable 优先级比 Serializable 更高
  3. 如果在序列化的时候使用了构造方法的情况下,那Externalizable 必须要创建默认的无参构造方法, Serializable 方法可以没有默认的无参构造方法

其中第三点,需要在在在注意一下,使用 Externalizable 的时候:
如果你在序列化的时候没有使用构造方法!!!!!
那么是可以不创建无参构造方法也能成功反序列化的
但是如果你使用了构造方法来进行序列化!!!!!
那么则必须创建一个无参构造方法,这样才能成功的反序列化

0x02 类方法讲解

  1. Externalizable 类主要有两个方法
  2. writeExternal() # 类被序列化时调用
  3. readExternal() # 类被反序列化时调用

0x03 例子

0x03.1 无构造方法例子

0x03.1.1 writeExternal()

  1. // 第一步创建 ExternalizableTest1 类
  2. package java反序列化测试;
  3. import java.io.Externalizable;
  4. import java.io.IOException;
  5. import java.io.ObjectInput;
  6. import java.io.ObjectOutput;
  7. public class ExternalizableTest1 implements Externalizable {
  8. public String test1;
  9. public transient String test2;
  10. @Override
  11. public void writeExternal(ObjectOutput out) throws IOException {
  12. out.writeObject("1111");
  13. out.writeObject("2222");
  14. System.out.println("writeExternal.......");
  15. }
  16. @Override
  17. public void readExternal(ObjectInput in) {
  18. }
  19. }
  1. // 第二步-序列化 ExternalizableTest1 类
  2. package java反序列化测试;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectOutputStream;
  6. public class SerializeDemo4 {
  7. public static void main(String[] args) {
  8. // ExternalizableTest1 序列化
  9. ExternalizableTest1 e = new ExternalizableTest1();
  10. try {
  11. FileOutputStream fileOut = new FileOutputStream("./src/main/java/java反序列化测试/ExternalizableTest1.ser");
  12. ObjectOutputStream out = new ObjectOutputStream(fileOut);
  13. out.writeObject(e);
  14. out.close();
  15. fileOut.close();
  16. } catch (IOException i) {
  17. i.printStackTrace();
  18. }
  19. }
  20. }
  21. // 运行结果:
  22. // 输出: writeExternal.......
  23. // 并且会在在 /src/main/java/java反序列化测试/ 生成一个 ExternalizableTest1.ser 文件

0x03.1.2 readExternal()

  1. // 第一步创建 ExternalizableTest2 类
  2. package java反序列化测试;
  3. import java.io.Externalizable;
  4. import java.io.IOException;
  5. import java.io.ObjectInput;
  6. import java.io.ObjectOutput;
  7. public class ExternalizableTest2 implements Externalizable {
  8. public String test1;
  9. public transient String test2;
  10. @Override
  11. public void writeExternal(ObjectOutput out) throws IOException {
  12. out.writeObject("1111");
  13. out.writeObject("2222");
  14. System.out.println("writeExternal.......");
  15. }
  16. @Override
  17. public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
  18. this.test1 = (String) in.readObject();
  19. this.test2 = (String) in.readObject();
  20. System.out.println("readExternal.......");
  21. }
  22. }
  1. // 第二步-序列化 ExternalizableTest2 类
  2. package java反序列化测试;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectOutputStream;
  6. public class SerializeDemo5 {
  7. public static void main(String[] args) {
  8. // ExternalizableTest2 序列化
  9. ExternalizableTest2 e = new ExternalizableTest2();
  10. try {
  11. FileOutputStream fileOut = new FileOutputStream("./src/main/java/java反序列化测试/ExternalizableTest2.ser");
  12. ObjectOutputStream out = new ObjectOutputStream(fileOut);
  13. out.writeObject(e);
  14. out.close();
  15. fileOut.close();
  16. } catch (IOException i) {
  17. i.printStackTrace();
  18. }
  19. }
  20. }
  21. // 运行结果:
  22. // 输出: writeExternal.......
  23. // 并且会在在 /src/main/java/java反序列化测试/ 生成一个 ExternalizableTest2.ser 文件
  1. // 第三步-反序列化 ExternalizableTest2 类
  2. package java反序列化测试;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectInputStream;
  6. public class DeserializationDemo5 {
  7. public static void main(String[] args) {
  8. // 反序列化 ExternalizableTest2
  9. try {
  10. FileInputStream fileIn = new FileInputStream("./src/main/java/java反序列化测试/ExternalizableTest2.ser");
  11. ObjectInputStream in = new ObjectInputStream(fileIn);
  12. ExternalizableTest2 e = (ExternalizableTest2) in.readObject();
  13. in.close();
  14. fileIn.close();
  15. System.out.println(e.test1);
  16. System.out.println(e.test2);
  17. } catch (IOException i) {
  18. i.printStackTrace();
  19. return;
  20. } catch (ClassNotFoundException c) {
  21. System.out.println("ExternalizableTest2 class not found");
  22. c.printStackTrace();
  23. return;
  24. }
  25. }
  26. }
  27. // 运行结果:
  28. // 输出:
  29. // readExternal() 被调用输出 readExternal.......
  30. // e.test1 被打印输出 1111
  31. // e.test2 被打印输出 2222

0x03.2 有构造方法例子

0x03.2.1 writeExternal()

  1. // 第一步创建 ExternalizableTest3 类
  2. package java反序列化测试;
  3. import java.io.Externalizable;
  4. import java.io.IOException;
  5. import java.io.ObjectInput;
  6. import java.io.ObjectOutput;
  7. public class ExternalizableTest3 implements Externalizable {
  8. public String test1;
  9. public transient String test2;
  10. public ExternalizableTest3() {
  11. }
  12. public ExternalizableTest3(String test1, String test2) {
  13. super();
  14. this.test1 = test1;
  15. this.test2 = test2;
  16. }
  17. @Override
  18. public void writeExternal(ObjectOutput out) throws IOException {
  19. out.writeObject(this.test1);
  20. out.writeObject(this.test2);
  21. System.out.println("writeExternal.......");
  22. }
  23. @Override
  24. public void readExternal(ObjectInput in) {
  25. }
  26. }
  1. // 第二步-序列化 ExternalizableTest3 类
  2. package java反序列化测试;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectOutputStream;
  6. public class SerializeDemo6 {
  7. public static void main(String[] args) {
  8. // ExternalizableTest3 序列化
  9. ExternalizableTest3 e = new ExternalizableTest3("test11", "test22");
  10. try {
  11. FileOutputStream fileOut = new FileOutputStream("./src/main/java/java反序列化测试/ExternalizableTest3.ser");
  12. ObjectOutputStream out = new ObjectOutputStream(fileOut);
  13. out.writeObject(e);
  14. out.close();
  15. fileOut.close();
  16. } catch (IOException i) {
  17. i.printStackTrace();
  18. }
  19. }
  20. }
  21. // 运行结果:
  22. // 输出: writeExternal.......
  23. // 并且会在在 /src/main/java/java反序列化测试/ 生成一个 ExternalizableTest3.ser 文件

0x03.2.2 readExternal()

  1. // 第一步创建 ExternalizableTest4 类
  2. package java反序列化测试;
  3. import java.io.Externalizable;
  4. import java.io.IOException;
  5. import java.io.ObjectInput;
  6. import java.io.ObjectOutput;
  7. public class ExternalizableTest4 implements Externalizable {
  8. public String test1;
  9. public transient String test2;
  10. public ExternalizableTest4() {
  11. }
  12. public ExternalizableTest4(String test1, String test2) {
  13. super();
  14. this.test1 = test1;
  15. this.test2 = test2;
  16. }
  17. @Override
  18. public void writeExternal(ObjectOutput out) throws IOException {
  19. out.writeObject(this.test1);
  20. out.writeObject(this.test2);
  21. System.out.println("writeExternal.......");
  22. }
  23. @Override
  24. public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
  25. this.test1 = (String) in.readObject();
  26. this.test2 = (String) in.readObject();
  27. System.out.println("readExternal.......");
  28. }
  29. }
  1. // 第二步-序列化 ExternalizableTest4 类
  2. package java反序列化测试;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectOutputStream;
  6. public class SerializeDemo7 {
  7. public static void main(String[] args) {
  8. // ExternalizableTest4 序列化
  9. ExternalizableTest4 e = new ExternalizableTest4("test11", "test22");
  10. try {
  11. FileOutputStream fileOut = new FileOutputStream("./src/main/java/java反序列化测试/ExternalizableTest4.ser");
  12. ObjectOutputStream out = new ObjectOutputStream(fileOut);
  13. out.writeObject(e);
  14. out.close();
  15. fileOut.close();
  16. } catch (IOException i) {
  17. i.printStackTrace();
  18. }
  19. }
  20. }
  21. // 运行结果:
  22. // 输出: writeExternal.......
  23. // 并且会在在 /src/main/java/java反序列化测试/ 生成一个 ExternalizableTest4.ser 文件
  1. // 第三步-反序列化 ExternalizableTest4 类
  2. package java反序列化测试;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectInputStream;
  6. public class DeserializationDemo6 {
  7. public static void main(String[] args) {
  8. // 反序列化 ExternalizableTest4
  9. try {
  10. FileInputStream fileIn = new FileInputStream("./src/main/java/java反序列化测试/ExternalizableTest4.ser");
  11. ObjectInputStream in = new ObjectInputStream(fileIn);
  12. ExternalizableTest4 e = (ExternalizableTest4) in.readObject();
  13. in.close();
  14. fileIn.close();
  15. System.out.println(e.test1);
  16. System.out.println(e.test2);
  17. } catch (IOException i) {
  18. i.printStackTrace();
  19. return;
  20. } catch (ClassNotFoundException c) {
  21. System.out.println("ExternalizableTest4 class not found");
  22. c.printStackTrace();
  23. return;
  24. }
  25. }
  26. }
  27. // 运行结果:
  28. // 输出:
  29. // readExternal() 被调用输出 readExternal.......
  30. // e.test1 被打印输出 test11
  31. // e.test2 被打印输出 test22