[Java] 对象的序列化和反序列化

 

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。 

  把Java对象转换为字节序列的过程称为对象的序列化。

  把字节序列恢复为Java对象的过程称为对象的反序列化。

  对象的序列化主要有两种用途:

  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

  2) 在网络上传送对象的字节序列。

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

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

 

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

 

 

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

 

  1. 创建一个对象输入流,它可以包装一个其他类型的输入流,比如文件输入流。
  2. 通过对象输入流的readObject()方法读取对象

 

其次在对象的序列化和反序列化过程当中,必须注意的事情是:为了能读出正确的数据,必须保证对象输出流的写对象的顺序与对象输入流读对象的顺序是一致的

 

 

 写道
package ser;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;

public class ObjectSaver {
public static void main(String[] args) throws Exception{
//1、创建一个对象输出流,它可以包装一个其他类型的输出流,比如文件输出流
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:\\objectFile.obj"));

String obj1 = "hello";

Date obj2 = new Date();

Customer obj3 = new Customer("WeiDong",24);
//2、通过对象输出流的out.writeObject()写对象——序列化对象
out.writeObject(obj1);
out.writeObject(obj2);
out.writeObject(obj3);
out.close();

//3、创建一个对象输入流,它可以包装一个其他类型的输入流,比如文件输入流——反序列化对象
ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:\\objectFile.obj"));
String obj11 = (String)in.readObject();
System.out.println(obj11);
System.out.println("obj11==obj1:" + (obj11==obj1));
System.out.println("obj11.equals(obj1):" + (obj11.equals(obj1)));

Date obj22 = (Date)in.readObject();
System.out.println(obj22);
System.out.println("obj22==obj2:" + (obj22==obj2));
System.out.println("obj22.equals(obj2):" + (obj22.equals(obj2)));

Customer obj33 = (Customer)in.readObject();
System.out.println(obj33);
System.out.println("obj33==obj3:" + (obj33==obj3));
System.out.println("obj33.equals(obj3):" + (obj33.equals(obj3)));
in.close();
}
}

 package ser;

Java代码
  1. import java.io.Serializable;   
  2.   
  3. public class Customer implements Serializable {   
  4.     private String username;   
  5.        
  6.     private int age;   
  7.        
  8.     public Customer(String username,int age) {   
  9.         this.username = username;   
  10.         this.age = age;   
  11.     }   
  12.     @Override  
  13.     public boolean equals(Object o) {   
  14.         if(this==o) {   
  15.             return true;   
  16.         }   
  17.            
  18.         if(!(o instanceof Customer)) {   
  19.             return false;   
  20.         }   
  21.            
  22.         final Customer other = (Customer)o;   
  23.            
  24.         if(this.username.equals(other.username)&&(this.age==other.age)) {   
  25.             return true;   
  26.         }else {   
  27.             return false;   
  28.         }   
  29.     }   
  30.     @Override  
  31.     public String toString() {   
  32.         return "username = " + username + "age = " + age;   
  33.     }   
  34.        
  35.        
  36.   
  37. }  
import java.io.Serializable;

public class Customer implements Serializable {
	private String username;
	
	private int 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 "username = " + username + "age = " + age;
	}
	
	

}

 

通常对象中的所有属性会被序列化,但是对于一些敏感的信息(比如用户的口令),一旦被序列化后,人们就可以通过读取文件或者拦截网络传输数据的方式来偷窥这些信息。因此处于对安全原因的考虑,应该禁止对这种属性进行说序列化。解决这种办法是把这种属性用transient来进行修饰,例如以下代码。

User.java代码
 

 package ser;

User.java代码
  1. import java.io.ByteArrayInputStream;   
  2. import java.io.ByteArrayOutputStream;   
  3. import java.io.ObjectInputStream;   
  4. import java.io.ObjectOutputStream;   
  5. import java.io.Serializable;   
  6.   
  7. /*   
  8.  * 属性包括用户名username和密码password   
  9.  * 构造方法来为对象的属性赋予合适的值   
  10.  */   
  11. public class User implements Serializable{   
  12.        
  13.     private String username;   
  14.        
  15.     private transient String password;   
  16.        
  17.     public User(String username,String password) {   
  18.         this.username = username;   
  19.            
  20.         this.password = password;   
  21.     }   
  22.   
  23.     @Override   
  24.     public String toString() {   
  25.         return username + "" + password;   
  26.     }   
  27.        
  28.     public static void main(String[] args) throws Exception{   
  29.         User user = new User("WeiDong","123456");   
  30.            
  31.         System.out.println("Before Serialization:" + user);   
  32.            
  33.         ByteArrayOutputStream buf = new ByteArrayOutputStream();   
  34.         //创建一个对象输出流,通过对象输出流的writeObject()写对象到输出流中   
  35.         ObjectOutputStream out = new ObjectOutputStream(buf);   
  36.            
  37.         out.writeObject(user);   
  38.            
  39.         out.close();   
  40.         //创建一个对象输入流,通过对象输入流的readObject()从输入流中读取对象   
  41.         ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()));   
  42.            
  43.         user = (User)in.readObject();   
  44.            
  45.         System.out.println("After Serialization:" + user);   
  46.            
  47.         in.close();   
  48.     }   
  49.        
  50. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值