`

有关Java序列化(三)——使用Externalizable

    博客分类:
  • Java
阅读更多

JDK中提供了另一个序列化接口--Externalizable,使用该接口之后,之前基于Serializable接口的序列化机制就将失效。Externalizable继承于Serializable,当使用该接口时,序列化的细节需要由程序员去完成。

测试代码:

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

public class Person implements Externalizable {

	private static final long serialVersionUID = -842029427676826563L;

	public static String name;
	private int age;
	private transient int workDay = 5;
	private String fClub;

	public Person() {
        System.out.println("none-arg constructor");
    }
	
	public Person(int age, String fClub) {
        this.age = age;
        this.fClub = fClub;
    }
	
	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getWorkDay() {
		return workDay;
	}

	public void setWorkDay(int workDay) {
		this.workDay = workDay;
	}

	public String getfClub() {
		return fClub;
	}

	public void setfClub(String fClub) {
		this.fClub = fClub;
	}

	private void writeObject(ObjectOutputStream out) throws IOException {
		out.defaultWriteObject();//执行默认的序列化机制
		out.writeInt(workDay);
		System.out.println("正在进行序列持久化");
	}

	private void readObject(ObjectInputStream in) throws IOException,
			ClassNotFoundException {
		in.defaultReadObject();
		workDay = in.readInt();
		System.out.println("读取持久化对象");
	}

	@Override
	public void readExternal(ObjectInput arg0) throws IOException,
			ClassNotFoundException {
		// TODO Auto-generated method stub
	}

	@Override
	public void writeExternal(ObjectOutput arg0) throws IOException {
		// TODO Auto-generated method stub	
	} 
}

 主测试类代码:

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

public class Hello {

	public static void main(String[] args) {
		Person person = new Person(26, "Juventus");
		person.setWorkDay(7);
		try {
			FileOutputStream fs = new FileOutputStream("foo.ser");
			ObjectOutputStream os = new ObjectOutputStream(fs);
			os.writeObject(person);
			os.close();

			Person.name = "Alex";

			FileInputStream in = new FileInputStream("foo.ser");
			ObjectInputStream s = new ObjectInputStream(in);
			Person p = (Person) s.readObject();
			System.out.println("name==" + Person.name + " age==" + p.getAge()
					+ " workDay==" + p.getWorkDay() + " fClub==" + p.getfClub());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 程序输出为:

none-arg constructor
name==Alex age==0 workDay==5 fClub==null

 

       从结果来看,writeObject和readObject没再被执行,Person p = (Person) s.readObject()读取持久化类的时候调用了Person的无参构造函数。同时发现,foo.ser文件里只有类的类型声明,没有任何实例变量,Person对象中任何一个字段都没有被序列化,所以打印结果里面,age为0,fClub为null,而workDay为初始值5。

        如上所示的代码,由于writeExternal()与readExternal()方法未作任何处理,那么该序列化行为将不会保存/读取任何一个字段。

更改Person类:

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

public class Person implements Externalizable {

	private static final long serialVersionUID = -842029427676826563L;

	public static String name;
	private int age;
	private transient int workDay = 5;
	private String fClub;

	public Person() {
        System.out.println("none-arg constructor");
    }
	
	public Person(int age, String fClub) {
        this.age = age;
        this.fClub = fClub;
    }
	
	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getWorkDay() {
		return workDay;
	}

	public void setWorkDay(int workDay) {
		this.workDay = workDay;
	}

	public String getfClub() {
		return fClub;
	}

	public void setfClub(String fClub) {
		this.fClub = fClub;
	}

	/*//writeObject和readObject不再被执行
	private void writeObject(ObjectOutputStream out) throws IOException {
		out.defaultWriteObject();//执行默认的序列化机制
		out.writeInt(workDay);
		System.out.println("正在进行序列持久化");
	}

	private void readObject(ObjectInputStream in) throws IOException,
			ClassNotFoundException {
		in.defaultReadObject();
		workDay = in.readInt();
		System.out.println("读取持久化对象");
	}
	*/

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		out.writeObject(fClub);
        out.writeInt(age);
        System.out.println("自定义序列化过程");
	} 
	
	@Override
	public void readExternal(ObjectInput in) throws IOException,
			ClassNotFoundException {
		fClub = (String) in.readObject();
        age = in.readInt();
        System.out.println("自定义反序列化");
	}
}

 主测试程序的输出结果为:

自定义序列化过程
none-arg constructor
自定义反序列化
name==Alex age==26 workDay==5 fClub==Juventus

        使用Externalizable进行序列化,当读取对象时,会调用被序列化类的无参构造器去创建一个新的对象,然后再将被保存对象的字段的值分别填充到新对象中。这就是为什么输出结果中会显示调动了无参构造器。由于这个原因,实现Externalizable接口的类必须要提供一个无参的构造器,且它的访问权限为public。

 

参考:

http://www.blogjava.net/jiangshachina/archive/2012/02/13/369898.html

分享到:
评论

相关推荐

    探索Java序列化与反序列化的奥秘:数据持久化的桥梁

    下面我们将详细探讨Java序列化的原理、实现方式以及一些常见的使用场景。 #### Java序列化的基本概念 Java序列化是指将对象的状态信息转换为字节序列的过程。这些字节序列可以被持久化到磁盘上,也可以通过网络...

    Java 序列化的秘密(高清PDF中文版)

    ### Java序列化的秘密 #### 为什么需要序列化 在探讨序列化之前,我们需要理解序列化产生的背景及其必要性。简而言之,Java程序本质上是由进程和内存构成的系统,在这个系统中,进程根据定义好的类生成一系列实例...

    关于Java您不知道的5件事

    通过本文的学习,读者不仅能了解到Java序列化的基础概念,还能掌握如何在实践中有效地运用这些知识点来解决实际问题。 二、知识点一:Java序列化允许随时间改变类型 1. **背景介绍**: - Java序列化是一种将Java...

    JAVA_IO操作总结——节点流和处理流.pdf

    - **`Externalizable` 接口**:扩展了 `Serializable` 接口,要求实现类提供 `readExternal` 和 `writeExternal` 方法,以便能够控制对象的状态如何被序列化和反序列化。 #### 五、特殊流(Special Streams) Java还...

    Java 的对象永续之道

    #### 三、Java中的序列化机制 Java为实现对象持久化提供了一种简单而强大的机制——序列化(Serialization)。通过实现`Serializable`接口,开发者几乎无需编写额外的代码就可以让对象支持序列化。序列化过程通常...

    JDK_API_1_6

    Externalizable Externalizable 实例类的唯一特性是可以被写入序列化流中,该类负责保存和恢复实例内容。 FileFilter 用于抽象路径名的过滤器。 FilenameFilter 实现此接口的类实例可用于过滤器文件名。 ...

    Brainbench Java Test

    - **最佳实践:**在多线程环境中,推荐采用选项4的方式——在一个同步块内克隆对象并序列化克隆的对象。这种方法能够有效避免因多线程并发操作而导致的数据不一致性问题。 #### 三、字符串分割工具类 - **问题描述...

    java面试题

    #### 六、什么是java序列化,如何实现java序列化? **序列化** 是将对象的状态转化为字节流以便存储或传输的过程。实现序列化的两种主要方式是: 1. **实现Serializable接口**:标记类可以被序列化。 2. **实现...

    简述抽象类和接口的区别-java接口和抽象类异同.docx

    - 例如,`Externalizable` 接口规定了对象序列化和反序列化的标准行为,实现此接口的类必须提供相应的实现代码。 #### 三、选择指导原则 - **单个继承与多重继承**: - 抽象类支持单一继承,即一个类只能继承一个...

Global site tag (gtag.js) - Google Analytics