java 那些鲜为人知的序列化(debug)

一:起因

Java提供一种机制叫做序列化,其实就是把实体类的对象(Bean对象)以二进制的形式就行存储和传输(读取),多有需要序列化的对象对应的类需要继承 接口 Serializable。

(1)通过有序的格式或者字节序列持久化java对象,其中包含对象的数据,还有对象的类型,和保存在对象中的数据类型。所以,如果我们已经序列化了一个对象,那么它可以被读取并通过对象的类型和其他信息进行反序列化,并最终获取对象的原型。
(2)ObjectInputStream 和 ObjectOutputStream对象是高级别的流对象,包含序列化和反序列化的方法。ObjectOutputStream 拥有很多序列化对象的方法,最常用的是:
(3)那么哪里会需要序列化呢?序列化通常在需要通过网络传输数据,或者保存对象到文件的场合使用。这里说的数据是对象而不是文本。
现在的问题是,我们的网络架构和硬盘都只能识别二进制和字节,而不能识别Java对象。序列化就是把Java对象中的value/states翻译为字节,以便通过网络传输或者保存。另外,反序列化就是通过读取字节码,并把它翻译回java对象

二:示例

(1)员工实体类(Employee.java  是一个bean,内含get set方法)

[java]

  1. import java.io.Serializable;  
  2. public class Employee implements Serializable{  
  3.    
  4.     int employeeId;  
  5.     String employeeName;  
  6.     String department;  
  7.        
  8.     public int getEmployeeId() {  
  9.         return employeeId;  
  10.     }  
  11.     public void setEmployeeId(int employeeId) {  
  12.         this.employeeId = employeeId;  
  13.     }  
  14.     public String getEmployeeName() {  
  15.         return employeeName;  
  16.     }  
  17.     public void setEmployeeName(String employeeName) {  
  18.         this.employeeName = employeeName;  
  19.     }  
  20.     public String getDepartment() {  
  21.         return department;  
  22.     }  
  23.     public void setDepartment(String department) {  
  24.         this.department = department;  
  25.     }  
  26. }  

(2)这里以存储在外部文件为例子,外部文件命名为employee.out (文件的读写以employee类的对象进行)

[java]

  1. import java.io.FileOutputStream;  
  2. import java.io.IOException;  
  3. import java.io.ObjectOutputStream;  
  4. import java.util.ArrayList;  
  5.  public class SerializeMain {  
  6.    
  7.  /** 
  8.   * @author zyp 
  9.   */  
  10.  public static void main(String[] args) {  
  11.    
  12.   Employee emp = new Employee();  
  13.   emp.setEmployeeId(101);  
  14.   emp.setEmployeeName(“zyp 张燕鹏”);  
  15.   emp.setDepartment(“com.CS”);  
  16.   Employee emp2 = new Employee();  
  17.   emp2.setEmployeeId(102);  
  18.   emp2.setEmployeeName(“xqz 徐勤柱”);  
  19.   emp2.setDepartment(“中国海洋大学”);  
  20.   ArrayList<Employee> emps = new ArrayList<Employee>();  
  21.   emps.add(emp);  
  22.   emps.add(emp2);  
  23.   // 以上两个用于测试的  
  24.   try  
  25.   {  
  26.    FileOutputStream fileOut = new FileOutputStream(“employee.out”,true);  
  27.    // employee.ser 这可是文件名称的,相当于序列化的文件名的内的内容的,无法用普通的文本查看器查看的  
  28.    ObjectOutputStream outStream = new ObjectOutputStream(fileOut);  
  29.    for(int i=0;i<emps.size();i++){  
  30.        outStream.writeObject(emps.get(i));  
  31.        System.out.println(emps.get(i));  
  32.    }  
  33.      
  34.    outStream.writeObject(null);// 非常关键的哦,否则报错的peekByte错误的,用于读取的时候判空的  
  35.    outStream.close();  
  36.    fileOut.close();  
  37.   }catch(IOException i)  
  38.   {  
  39.    i.printStackTrace();  
  40.   }  
  41.  }  
  42. }  

(3)读取(2)存储的文件

[java]

  1. import java.io.FileInputStream;  
  2. import java.io.IOException;  
  3. import java.io.ObjectInputStream;  
  4. import java.util.ArrayList;  
  5.    
  6. public class DeserializeMain {  
  7.  /** 
  8.   * @author zyp 
  9.   */  
  10.  public static void main(String[] args) {  
  11.   ArrayList<Employee> emps = new ArrayList<Employee>();   
  12.   Employee emp = null;  
  13.        try  
  14.        {  
  15.           FileInputStream fis =new FileInputStream(“employee.out”);  
  16.           //employee.ser 这可是之前保存的文件名称的,相当于读取序列化的文件名的内的内容的,无法用普通的文本查看器查看的  
  17.           ObjectInputStream ois = new ObjectInputStream(fis);  
  18.           emp = (Employee) ois.readObject();  
  19. //  
  20.           while(emp!=null){  
  21.               emps.add(emp);  
  22.               emp = (Employee)ois.readObject();  
  23.           }  
  24.           ois.close();  
  25.           fis.close();  
  26.        }catch(IOException i)  
  27.        {  
  28.           i.printStackTrace();  
  29.           return;  
  30.        }catch(ClassNotFoundException c)  
  31.        {  
  32.           System.out.println(“Employee class not found”);  
  33.           c.printStackTrace();  
  34.           return;  
  35.        }  
  36.        for(int i=0;i<emps.size();i++){  
  37.            emp = emps.get(i);  
  38.            System.out.println(“Deserialized Employee…”);  
  39.            System.out.println(“Emp id: “ + emp.getEmployeeId());  
  40.            System.out.println(“Name: “ + emp.getEmployeeName());  
  41.            System.out.println(“Department: “ + emp.getDepartment());  
  42.            System.out.println(emp);  
  43.        }  
  44.          
  45.  }  
  46. }  

(4)注意事项:

outStream.writeObject(null); (2)中的这一句话,非常关键的哦,否则报错的peekByte错误的,这是用于读取的时候判空的,否者到了文件末尾EOF还在读取employee对象,肯定报错的,错误如下(如果没有这句代码的话)


错误提示


(5)employee.out文件是以16进制进行数据存储的,一般的notepad++文本文件打不开的,UE可以打开的查看16进制代码

(6)eclipse 调试说明:首先打开debug模式(视图)开启,之后设置断点(设置多个断点)

标签