java的序列化

来源:互联网 发布:看天下杂志知乎 编辑:程序博客网 时间:2024/04/30 07:37
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。 
  把Java对象转换为字节序列的过程称为对象的序列化。 
  把字节序列恢复为Java对象的过程称为对象的反序列化。 
  对象的序列化主要有两种用途: 
  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中; 


  2) 在网络上传送对象的字节序列。 
Java语言中要求只有实现了java.io.Serializable接口的类的对象才能被序列化及反序列化。JDK类库中的有些类(如String类、包装类(Java语言用包装类来把基本类型数据转换为对象,基本类型数据有四类八种)和Date类等)都实现了Serializable接口。 
对象的序列化包括以下步骤。 


1.创建一个对象输出流,它可以包装一个其他类型的输出流,比如文件输出流。    
2.通过对象输出流的writeObject()写对象。 


对象的反序列化包括以下步骤。


1.创建一个对象输入流,它可以包装一个其他类型的输入流,比如文件输入流。 
2.通过对象输入流的readObject()方法读取对象 
其次在对象的序列化和反序列化过程当中,必须注意的事情是:为了能读出正确的数据,必须保证对象输出流的写对象的顺序与对象输入流读对象的顺序是一致的。 


例子:用String,Date类和自己编写的Customer类序列化后,再反序列. 
创建一个Customer的类,针对Custmoer重写equals方法 
package javaserializabletest;   
import java.io.Serializable;   
  
public class Customer implements Serializable  {   
    private String username;   
    private int age;   
  
    public String getUsername() {   
        return username;   
    }   
  
    public void setUsername(String username) {   
        this.username = username;   
    }   
  
    public int getAge() {   
        return age;   
    }   
  
    public void setAge(int age) {   
        this.age = age;   
    }   
    public Customer(String username,int age){   
        this.username =username;   
        this.age=age;   
    }   
    @Override  
  public boolean equals(Object o)   
  {   
      if(this==o){   
          return true;   
      }   
      if(!(o instanceof Customer )){   
          return false;   
      }   
      final Customer other=(Customer)o;   
      if(this.username.equals(other.username)&&(this.age==other.age)){   
          return true;   
      }else{   
          return false;   
      }   
  }   
    @Override  
  public String toString(){   
      return "usename:"+username+" age:"+age;   
  }         
}  
package danel.testSerializable;   
import java.io.FileInputStream;   
import java.io.FileOutputStream;   
import java.io.ObjectInputStream;   
import java.io.ObjectOutputStream;   
import java.util.Date;   
import javaserializabletest.Customer;   
public class ObjectSave {   
public static void  main(String[] args)throws Exception{   
   //创建一个对象输出流,它可以包装一个其他类型的输出流,比如文件输出流   
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:\\daniel.obj"));   
       
    String title="daniel_testing";   
    Date current=new Date();   
    Customer c = new Customer("daniel",26);   
    //通过对象输出流的out.writeObject()写对象——序列化对象   
    out.writeObject(title);   
    out.writeObject(current);   
    out.writeObject(c);   
    out.close();   
    //创建一个对象输入流,它可以包装一个其他类型的输入流,比如文件输入流——反序列化对象   
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:\\daniel.obj"));   
    String title1 = (String)in.readObject();   
    System.out.println("*********************************");   
    System.out.println(title1);   
    System.out.println("title==title1:"+(title==title1));   
    System.out.println("title.equals(title1):"+title.equals(title1));   
    System.out.println("*********************************");   
    //System.out.println(c.toString());   
     
    Date current1 = (Date)in.readObject();   
    System.out.println(current1);   
    System.out.println("curren==current1:"+(current==current1));   
    System.out.println("current.equals(current1)"+current.equals(current1));   
    System.out.println("*********************************");   
    Customer c1 = (Customer)in.readObject();   
    System.out.println(c1);   
    System.out.println("c==c1:"+(c==c1));   
    System.out.println("c.equals(c1):"+c.equals(c1));   
    System.out.println("*********************************");   
    in.close();   
}   
}  
通常对象中的所有属性会被序列化,但是对于一些敏感的信息(比如用户的口令),一旦被序列化后, 
人们就可以通过读取文件或者拦截网络传输数据的方式来偷窥这些信息。 
因此处于对安全原因的考虑,应该禁止对这种属性进行说序列化。 
解决这种办法是把这种属性用transient来进行修饰,例如以下代码。 


package danel.testSerializable;   
import java.io.ByteArrayInputStream;   
import java.io.ByteArrayOutputStream;   
import java.io.ObjectInputStream;   
import java.io.ObjectOutputStream;   
import java.io.Serializable;   
  
public class User implements Serializable {   
    private String username;   
    private transient String password;   
    public User(String username,String password){   
        this.username = username;   
        this.password = password;   
    }   
   public static void main(String[] args) throws Exception{   
       User user = new User("daniel","123456");   
       System.out.println("Before Serializable"+user.username+"--"+user.password);   
       ByteArrayOutputStream buf = new ByteArrayOutputStream();   
       ObjectOutputStream out = new ObjectOutputStream(buf);   
       out.writeObject(user);   
       out.close();   
       ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()));   
      user = (User)in.readObject();   
      System.out.println("After Serializable:"+user.username+"--"+user.password);   
   }   
}    
原创粉丝点击