java中序列化与反序列化的冷知识

1.java中如何实现序列化和反序列化

    下面的代码是进行序列化的简单实例

 

[java] view plaincopy技术分享技术分享
 
  1. public static void main(String[] args) {  
  2.   
  3.         System.out.println("-----------------序列化----------------------↓");  
  4.   
  5.         Student student1 = new Student(10, "zhao");  
  6.         Student student2 = new Student(15, "kai");  
  7.         Student student3 = new Student(20, "qiang");  
  8.   
  9.         ObjectOutputStream objectWriter = null;  
  10.   
  11.         try {  
  12.   
  13.             objectWriter = new ObjectOutputStream(new FileOutputStream(  
  14.                     new File("./Serializable")));  
  15.   
  16.             objectWriter.writeObject(student1);  
  17.             objectWriter.writeObject(student2);  
  18.             objectWriter.writeObject(student3);  
  19.   
  20.         } catch (Exception e) {  
  21.             e.printStackTrace();  
  22.         } finally {  
  23.   
  24.             try {  
  25.                 objectWriter.close();  
  26.             } catch (IOException e) {  
  27.                 e.printStackTrace();  
  28.             }  
  29.   
  30.         }  
  31.   
  32.         System.out.println("-----------------反序列化----------------------↓");  
  33.         ObjectInputStream objectInputStream = null;  
  34.         try {  
  35.             objectInputStream = new ObjectInputStream(new FileInputStream(  
  36.                     new File("./Serializable")));  
  37.   
  38.             Student s1 = (Student) objectInputStream.readObject();  
  39.             Student s2 = (Student) objectInputStream.readObject();  
  40.             Student s3 = (Student) objectInputStream.readObject();  
  41.   
  42.             System.out.println(s1.toString());  
  43.             System.out.println(s2.toString());  
  44.             System.out.println(s3.toString());  
  45.   
  46.         } catch (Exception e) {  
  47.             e.printStackTrace();  
  48.         } finally {  
  49.             try {  
  50.                 objectInputStream.close();  
  51.             } catch (IOException e) {  
  52.                 e.printStackTrace();  
  53.             }  
  54.         }  
  55.   
  56.     }  


    2.在反序列化的时候,需要调用本类的构造函数吗?

 

    我的测试序列化的类如下,在无参和有参的构造函数中,打印了语句,然后,我们使用上面的序列化和反序列化代码进行测试。

[java] view plaincopy技术分享技术分享
 
  1. public class Student implements Serializable {  
  2.   
  3.     private int age;  
  4.     private String name;  
  5.   
  6.     public Student() {  
  7.         System.out.println("Student()");  
  8.     }  
  9.   
  10.     public Student(int age, String name) {  
  11.         this.age = age;  
  12.         this.name = name;  
  13.         System.out.println("Student(int age, String name)");  
  14.     }  
  15.   
  16.     @Override  
  17.     public String toString() {  
  18.         return "Student [age=" + age + ", name=" + name + "]";  
  19.     }  
  20.   
  21. }  

 

 

    下面是测试结果

 

[html] view plaincopy技术分享技术分享
 
  1. -----------------序列化----------------------↓  
  2. Student(int age, String name)  
  3. Student(int age, String name)  
  4. Student(int age, String name)  
  5. -----------------反序列化----------------------↓  
  6. Student [age=10, name=zhao]  
  7. Student [age=15, name=kai]  
  8. Student [age=20, name=qiang]  


    因此,我们可以认为,在反序列化的时候,是不需要调用本类的构造函数的。

 

 

    2.反序列化的时候,会调用父类的构造函数吗?

    我们新创建一个Person类,然后用Student继承自Person,Student的代码如下

 

[java] view plaincopy技术分享技术分享
 
  1. public class Student extends Person implements Serializable {  
  2.   
  3.     private int age;  
  4.     private String name;  
  5.   
  6.     public Student() {  
  7.         System.out.println("Student()");  
  8.     }  
  9.   
  10.     public Student(int age, String name) {  
  11.         this.age = age;  
  12.         this.name = name;  
  13.         System.out.println("Student(int age, String name)");  
  14.     }  
  15.   
  16.     @Override  
  17.     public String toString() {  
  18.         return "Student [age=" + age + ", name=" + name + "]";  
  19.     }  
  20.   
  21. }  


    Person类的代码如下

 

 

[java] view plaincopy技术分享技术分享
 
  1. public class Person {  
  2.   
  3.     private boolean sex;  
  4.   
  5.     public Person() {  
  6.         System.out.println("Person()");  
  7.     }  
  8.   
  9.     public Person(boolean sex) {  
  10.         this.sex = sex;  
  11.         System.out.println("Person(boolean sex)");  
  12.     }  
  13.   
  14.     @Override  
  15.     public String toString() {  
  16.         return "Person [sex=" + sex + "]";  
  17.     }  
  18.   
  19. }  


    同样,我把Person的构造函数都进行了输出,然后利用上面的代码进行测试,下面是测试结果

 

 

[html] view plaincopy技术分享技术分享
 
  1. -----------------序列化----------------------↓  
  2. Person()  
  3. Student(int age, String name)  
  4. Person()  
  5. Student(int age, String name)  
  6. Person()  
  7. Student(int age, String name)  
  8. -----------------反序列化----------------------↓  
  9. Person()  
  10. Person()  
  11. Person()  
  12. Student [age=10, name=zhao]  
  13. Student [age=15, name=kai]  
  14. Student [age=20, name=qiang]  


    我们可以看到,虽然Student的构造函数没有调用,但是Person的无参构造函数却调用了,这也就是说,在反序列化的时候,本类的构造函数不会调用,但是会调用其父类的无参构造函数。在没有继承的情况下,会调用所有类的父类,即Object的构造函数。

 

 

    3.当需要序列化的类的父类没有实现序列化的时候,能否将父类中protect的属性进行序列化和反序列化呢?

    为了进行测试,我们需要将Person类的代码进行修改,下面修改之后的代码

 

[java] view plaincopy技术分享技术分享
 
  1. public class Person {  
  2.   
  3.     protected boolean sex;  
  4.   
  5.     public Person() {  
  6.         System.out.println("Person()");  
  7.     }  
  8.   
  9.     public Person(boolean sex) {  
  10.         this.sex = sex;  
  11.         System.out.println("Person(boolean sex)");  
  12.     }  
  13.   
  14.     @Override  
  15.     public String toString() {  
  16.         return "Person [sex=" + sex + "]";  
  17.     }  
  18.   
  19. }  


    同时,我们还需要修改Student的toString(),下面是修改之后Student代码

 

 

[java] view plaincopy技术分享技术分享
 
  1. public class Student extends Person implements Serializable {  
  2.   
  3.     private int age;  
  4.     private String name;  
  5.   
  6.     public Student() {  
  7.         System.out.println("Student()");  
  8.     }  
  9.   
  10.     public Student(int age, String name) {  
  11.         this.age = age;  
  12.         this.name = name;  
  13.         System.out.println("Student(int age, String name)");  
  14.     }  
  15.   
  16.     public Student(int age, String name, boolean sex) {  
  17.         super(sex);  
  18.         this.age = age;  
  19.         this.name = name;  
  20.     }  
  21.   
  22.     @Override  
  23.     public String toString() {  
  24.         return "Student [age=" + age + ", name=" + name + ", sex=" + sex + "]";  
  25.     }  
  26.   
  27. }  


    我们进行序列化和反序列化,下面是测试结果

 

 

[html] view plaincopy技术分享技术分享
 
  1. -----------------序列化----------------------↓  
  2. Person(boolean sex)  
  3. Person(boolean sex)  
  4. Person()  
  5. Student(int age, String name)  
  6. http://www.metell.net/post/4.html
  7. -----------------反序列化----------------------↓  
  8. Person()  
  9. Person()  
  10. Person()  
  11. http://www.metell.net/post/3.html
  12. Student [age=10, name=zhao, sex=false]  
  13. Student [age=15, name=kai, sex=false]  
  14. Student [age=20, name=qiang, sex=false]  


    从结果中可以看到,虽然父类没有进行序列化,但是sex属性也参与了序列化和反序列化操作,因此不影响。

 

 

    从上面几个测试的结果中,我们可以得出结论:进行序列化和反序列化必须调用其父类的无参的构造函数。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。