Java序列化学习笔记

 

     Java 对象序列化为二进制文件的技术是 Java 系列技术中一个较为重要的技术点,在大多数情况下,只需要了解被序列化的类需要实现 Serializable 接口,使用 ObjectInputStream 和 ObjectOutputStream 进行序列化和反序列化即可。

     在工作中,经常会碰到序列化的情况,因为我们调用的东西不可能都在本地,往往需要通过RMI,一些远程接口调用。这样数据序列化的技术更显得重要。而java序列化技术为我们实现这些远程调用提供了技术保障。

 

一. 序列化的ID,请看如下代码

片段一:

 

[java]  view plain copy print ?
  1. public class Person implements Serializable{  
  2.     private static final long serialVersionUID = 1L;  
  3.     private int age;  
  4.       
  5.     private String name;  
  6.       
  7.     private String mobile;  
  8.       
  9.     private transient String address;  //不被序列化的属性  
  10. }  
 

片段二:

[java]  view plain copy print ?
  1. public class Person implements Serializable{  
  2.     private static final long serialVersionUID = 2L;  
  3.     private int age;  
  4.       
  5.     private String name;  
  6.       
  7.     private String mobile;  
  8.       
  9.     private transient String address;  //不被序列化的属性  
  10. }  
 

两个类除了serialVersionUID,其余完全一样,但这两个类是不能被序列化与反序列化的,所以在写程序时,实现了序列化的类,serialVersionUID一定要一致,否则客户端与服务端将不匹配,会因serialVersionUID不匹配导致意想不到的问题。当然也可以通过服务端强制更新serialVersionUID值,让客户端主动报错,来强制更新程序。

 

二.子类实现Serializable接口,而父类并没有实现Serializable 接口

父类:Person.java

[java]  view plain copy print ?
  1. /** 
  2.  * Created on 2011-3-11 
  3.  * @author         shixing_11@sina.com 
  4.  * @version        1.0 
  5.  */  
  6. public class Person {  
  7.     private int age;  
  8.       
  9.     private String name;  
  10.       
  11.     private String mobile;  
  12.       
  13.     private transient String address;  //不被序列化的属性  
  14.       
  15.     public Person(){  
  16.         System.out.println("父类没有实现序列化接口时,默认构造器会被调用");  
  17.     }  
  18.       
  19.     public Person(String name,int age){  
  20.         this.name = name;  
  21.         this.age = age;  
  22.     }  
  23.       
  24.     public int getAge(){  
  25.         return age;  
  26.     }  
  27.     public void setAge(int age){  
  28.         this.age = age;  
  29.     }  
  30.     public String getName(){  
  31.         return name;  
  32.     }  
  33.     public void setName(String name){  
  34.         this.name = name;  
  35.     }  
  36.     public String getMobile(){  
  37.         return mobile;  
  38.     }  
  39.     public void setMobile(String mobile){  
  40.         this.mobile = mobile;  
  41.     }  
  42.       
  43.     public void setAddress(String address) {  
  44.         this.address = address;  
  45.     }  
  46.       
  47.     public String getAddress(){  
  48.         return address;  
  49.     }  
  50.       
  51. }  
 

子类:Student.java

[java]  view plain copy print ?
  1. /** 
  2.  * Created on 2011-3-11 
  3.  * @author shixing_11@sina.com 
  4.  * @version        1.0 
  5.  */  
  6. public class Student extends Person implements Serializable  
  7. {  
  8.     public Student(String name, int age){  
  9.         super(name, age);  
  10.     }  
  11.     private static final long serialVersionUID = 1L;  
  12.       
  13.     public static String S_T = "static属性不能被序列化";    
  14.       
  15.     private int no;  
  16.       
  17.     private String schoolName;  
  18.       
  19.     public void setSchoolName(String schoolName){  
  20.         this.schoolName = schoolName;  
  21.     }  
  22.       
  23.     public String getSchoolName(){  
  24.         return schoolName;  
  25.     }  
  26.       
  27.     public void setNo(int no){  
  28.         this.no = no;  
  29.     }  
  30.       
  31.     public int getNo(){  
  32.         return no;  
  33.     }  
  34. }  
 

做如下测试:

[java]  view plain copy print ?
  1. /** 
  2.  * Created on 2011-3-11 
  3.  * @author shixing_11@sina.com 
  4.  * @version        1.0 
  5.  */  
  6. public class SerializeTest  
  7. {  
  8.     public static void main(String[] args){  
  9.         Student student = new Student("shixing_11",27);  
  10.         student.setMobile("1515808XXXX");  //父类的属性  
  11.         student.setAddress("浙江省杭州市"); //父类的属性  
  12.         student.setNo(1111111);   //子类自有属性  
  13.         student.setSchoolName("XX理工大学"); //子类自有属性  
  14.         serializeObject(student);  //序列化方法  
  15.         Student.S_T = "我是static,我的值被改";  
  16.         deSerializeObject();   //反序列化  
  17.     }  
  18.       
  19.     private static void deSerializeObject() {  
  20.         try{  
  21.             InputStream is = new FileInputStream("C://ss.ser");  
  22.             ObjectInputStream ois = new ObjectInputStream(is);  
  23.             Student student = (Student)ois.readObject();  
  24.             ois.close();  
  25.             System.out.println(Student.S_T);  
  26.             System.out.println(student.getNo());  
  27.             System.out.println(student.getSchoolName());  
  28.         }catch (ClassNotFoundException e){  
  29.             e.printStackTrace();  
  30.         }catch (FileNotFoundException e){  
  31.             e.printStackTrace();  
  32.         } catch (IOException e){  
  33.             e.printStackTrace();  
  34.         }  
  35.     }  
  36.     public static void serializeObject(Person person){  
  37.         try{  
  38.             OutputStream os = new FileOutputStream("C://ss.ser");  
  39.             ObjectOutputStream ois = new ObjectOutputStream(os);  
  40.             ois.writeObject(person);  
  41.             ois.close();  
  42.         }catch (FileNotFoundException e){  
  43.             e.printStackTrace();  
  44.         }catch (IOException e){  
  45.             e.printStackTrace();  
  46.         }  
  47.     }  
  48. }  
 

运行结果:

结论: 

 

1. 声明为 transient 型的属性是不被序列化的。

2. S_T属性的值被改变了,本来是序列时保存进去的是"static属性不能被序列化“,但读出来发现该值被改变,说明static声明的属性并没有     被写进文件里,所以声明为static型的属性是不被序列化的。

3. 子类实现Serializable接口,父类未实现Serializable接口,反序列化时父类的属性会被恢复成原始值,即int 0 ,String null.

    父类必须有无参的构造方法,因为如果父类实现了Serializable接口,则会直接从序列化过的文件里反序列化,读出来原来的对象即可,

    但若父类没有实现Serializable接口,则无法直接读取,所以只有调父类的默认构造器创建出该类的对象,再进行属性填充。

 

三.父类实现了Serializable接口的情况较简单,只需记住规则,如果父类实现了Serializable接口,则子类默认也可被序列化,不需要显式声明Serializable接口。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值