【JAVA基础】Serializable 和Externalizable 序列化详解

本文介绍了对象序列化的概念及其两种主要用途:将对象持久化到硬盘和在网络上传输对象。详细探讨了Java中实现序列化的Serializable和Externalizable接口,并通过具体示例展示了如何使用这两种接口进行对象的序列化和反序列化。

什么是序列化

对象的序列化一般有两种用途:把对象的字节序列永久地保存到硬盘上,通常存放在一个指定文件中;或者在网络上传送对象的字节序列。而把字节序列恢复为对象的过程称为对象的反序列化。归纳起来,就是把你的数据换个时间和/或换个地方,继续使用换个时间,比如存盘,换个地方,比如网络传输,当然,实现“换个时间/地方用”的方式很多很多。

 

实现序列化功能的两个接口Serializable 和 Externalizable 详解

(1)Serializable接口 
(2)Externalizable接口:该接口继承了Serializable接口,是对Serializable的扩展,并提供了readExternal(ObjectInput in)和writeExternal(ObjectOutout out)两种方法,通过重写这两个方法来实现自身的序列化行为的控制。在对实现了Externalizable的类的对象进行反序列化时,会先调用该类的无参构造函数,若无参构造函数被删除或被设置为private、default或protected时会抛出java.io.InvalidException:no valid construction

 

Serializable 序列化例子如下:

/**
 * 实体类
 */
class  Peaple implements Serializable{
	

	private static final long serialVersionUID = 1L;
	
	String name;
	
	 String age;

	public Peaple(String name,String age){
		this.name=name;
	    this.age=age;
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "name="+name+"age="+age;
	}
	
	
}
public static void main(String[] args) {
		
		Peaple peaple=new Peaple("mayou","18");
		
		System.out.println(peaple.toString());
		
		try {
			ObjectOutputStream objOutput=new ObjectOutputStream(new FileOutputStream("D://mayou.txt"));
			
			objOutput.writeObject(peaple);
			
			objOutput.close();
			
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D://mayou.txt"));
			
			peaple = (Peaple)ois.readObject();
			
			System.out.println(peaple.toString());
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}	

 

Externalizable接口是Serializable接口的子接口,在此接口中定义了两个方法,这两个方法的作用如下。

writeExternal(ObjectOutput out):在此方法中指定要保存的属性信息,对象序列化时调用。

readExternal(ObjectInput in):在此方法中读取被保存的信息,对象反序列化时调用。

这两个方法的参数类型是ObjectOutput和ObjectInput,两个接口的定义如下。

ObjectOutput接口定义:

public interface ObjectOutput extends DataOutput

ObjectInput接口定义:

public interface ObjectInput extends DataInput

可以发现以上两个接口分别继承DataOutput和DataInput,这样在这两个方法中就可以像DataOutputStream和DataInputStream那样直接输出和读取各种类型的数据。

如果一个类要使用Externalizable实现序列化时,在此类中必须存在一个无参构造方法,因为在反序列化时会默认调用无参构造实例化对象,如果没有此无参构造,则运行时将会出现异常,这一点的实现机制与Serializable接口是不同的。

范例如下:

public class ExternalizableDemo implements Externalizable{

    String name;
	
	String age;
	
	String sex;
	
	public ExternalizableDemo(String name,String age,String sex){
		this.name=name;
		this.age=age;
		this.sex=sex;
		
	}

	public ExternalizableDemo(){}
	
	public void writeExternal(ObjectOutput out) throws IOException {
		// TODO Auto-generated method stub
		
		out.writeObject(name);
		out.writeObject(age);
		
		
	}

	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		// TODO Auto-generated method stub
		//按照 out.writeObject() 的顺序逐一取出
	
		this.name=(String)in.readObject();
		
		this.age=(String)in.readObject();
		
		
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "name="+name+"age="+age+"sex="+sex;
	}
	
	
	public static void main(String[] args) {
		
		ExternalizableDemo peaple=new ExternalizableDemo("mayou", "18", "man");
		
	    System.out.println(peaple.toString());
		
		try {
			ObjectOutputStream objOutput=new ObjectOutputStream(new FileOutputStream("D://mayou.txt"));
			
			objOutput.writeObject(peaple);
			
			objOutput.close();
			
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D://mayou.txt"));
			
			peaple = (ExternalizableDemo)ois.readObject();
			
			System.out.println(peaple.toString());
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

 

注意事项

  • 1.只有实现了Serializable或Externalizable的类的对象才可以实现序列化。

  • 2.对象和对象数组都可以实现序列化

  • 3.若一个父类实现了Serializable或Externalizable接口,其子类均实现了Serializable或Externalizable接口。

  • 4.实现Serializable或Externalizable接口的类应提供无参构造函数

  • 5.static的属性和方法不能被序列化,因为static的属性和方法与对象无关,而序列化和反序列化则是针对对象而言的。

  • 6.对于不希望被序列化的非static成员和方法可以使用transient关键字标明

  • 7.若一个序列化子类的父类是非序列化的,则该子类从父类继承下来的变量将恢复其默认初始值而不被初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值