`

有关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 串行化(序列化)Serializable/Externalizable

    在 serializable-prj 项目中,可能包含了各种示例代码,展示了如何在Java中实现和使用序列化功能。 综上所述,Java的序列化和外部化是实现对象持久化和跨进程通信的关键技术。理解并熟练掌握这些概念,能够帮助...

    java序列化和反序列化的方法

    * 使用 Externalizable 接口实现序列化和反序列化 * 使用 Java 序列化 API 实现序列化和反序列化 在实际开发中,选择合适的序列化和反序列化方法取决于具体的需求和场景。在本例中,我们使用 Serializable 接口实现...

    Java对象序列化标准最新版

    为此,Java提供了一些机制来保护这些信息,例如使用`transient`关键字来标识不希望序列化的字段。 #### 二、对象输出类 **2.1 `ObjectOutputStream`类** `ObjectOutputStream`类负责将对象写入序列化流。它可以将...

    java对象序列化.ppt

    要实现对象序列化,Java类必须实现`Serializable`接口或`Externalizable`接口。`Serializable`接口是一个空接口,当一个类实现它时,表明该类的所有实例都可以被序列化。而`Externalizable`接口提供了更多的控制权,...

    Java实现序列化例子

    6. **序列化框架**:除了Java内置的序列化机制,还有一些第三方库,如Google的Protocol Buffers,Apache的Avro,和JSON序列化库如Jackson和Gson,它们提供了更高效、更灵活的数据序列化解决方案。 7. **序列化与...

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

    为了支持序列化功能,Java定义了一个特殊的接口——`java.io.Serializable`,任何实现了这个接口的类都可以被序列化。 #### 序列化的过程 序列化的过程主要包括两个步骤:序列化和反序列化。 1. **序列化**:将...

    java序列化与反序列化

    Java序列化是将Java对象转换为字节流的过程,以便可以在磁盘、数据库或网络上存储或传输这些对象。这使得我们能够保存对象的状态,并在稍后的时间点恢复它,或者在网络之间传递对象。反序列化是相反的过程,即从字节...

    Java 文件 序列化 读写

    下面将详细介绍Java文件序列化读写的相关知识点。 1. **序列化的目的**: - **持久化对象**:将对象状态保存到文件或数据库中,即使程序关闭,下次启动时仍能恢复。 - **跨网络传输**:在网络通信中,通过序列化...

    java序列化方式Java系列2021.pdf

    Java序列化主要有两种方式:隐式序列化(实现Serializable接口)和显式序列化(实现Externalizable接口)。 ### 隐式序列化 **实现Serializable接口**:这是最常见也是最简单的一种序列化方式。只要一个类实现了`...

    java序列化和反序列化1

    Java的序列化和反序列化是Java开发中重要的概念,主要涉及对象状态的...总之,Java的序列化和反序列化是处理对象持久化和网络传输的关键技术,但在使用过程中需要注意安全性和性能优化,以确保代码的健壮性和高效性。

    深入理解Java虚拟机-Java内存区域透彻分析(序列化、反序列化概念及其使用场景+实现序列化的方式+transient关键字)

    深入理解Java虚拟机-Java内存区域透彻分析(序列化、反序列化概念及其使用场景+实现序列化的方式+transient关键字) Java序列化和反序列化是Java虚拟机中的一种重要机制,它们可以将Java对象转换为二进制数据,然后...

    java基础 对象序列化

    2. **序列化过程**:使用`java.io.ObjectOutputStream`类的`writeObject()`方法将对象写入输出流。 3. **反序列化过程**:使用`java.io.ObjectInputStream`类的`readObject()`方法从输入流中读取对象。 #### 文件...

    Java序列化(Serializable)与反序列化__1.docx

    Java序列化(Serializable)是Java...总的来说,Java序列化是一个强大但需要谨慎使用的工具,正确理解和使用序列化可以帮助我们实现对象的持久化和跨进程通信,同时也需要关注其中的安全隐患,以确保应用程序的安全性。

    Java中的序列化与反序列化.pdf

    另外,Java还提供了一个更灵活的序列化接口`Externalizable`,它要求类自己控制序列化和反序列化的过程,需要实现`writeExternal()`和`readExternal()`方法。这种方式更耗费资源,但能更好地控制序列化过程,特别是...

    java序列化深度探讨

    Java对象的序列化是Java平台提供的一种持久化机制,它允许将对象的状态转换为字节流,以便存储在...理解序列化的原理以及如何正确使用`Serializable`和`Externalizable`接口,对于开发高质量的Java应用程序至关重要。

    JAVA对象的序列化与反序列化详细PPT课件.pptx

    Java对象的序列化和反序列化是Java编程中的一项重要技术,主要应用于数据持久化、网络传输等场景。本课件详细介绍了这一概念及其在实际应用中的操作。 首先,序列化是将Java对象转化为字节序列的过程,目的是为了...

    java序列化对象的存储和读取共6页.pdf.zip

    Java序列化是Java平台中的一种标准机制,它允许将对象的状态转换为字节流,以便进行持久化存储、网络传输或在不同Java虚拟机之间共享。这个过程被称为序列化,而将字节流恢复为原来的对象状态的过程则称为反序列化。...

    Java 对象序列化详解以及实例实现和源码下载

    Java中的序列化机制有两种实现方式: 一种是实现Serializable接口 另一种是实现Externalizable接口 区别: 实现Serializable接口 1 系统自动储存必要的信息 2 Java内建支持,易于实现,只需实现该接口即可,无须任何...

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

    除了使用Java标准库提供的序列化机制外,开发者还可以通过实现`Externalizable`接口来自定义序列化和反序列化逻辑。这种方式提供了更高的灵活性,允许开发者控制对象的状态如何被序列化和反序列化。 #### 严重漏洞...

Global site tag (gtag.js) - Google Analytics