`

理解Java对象序列化——Serializable接口

    博客分类:
  • java
阅读更多
概述:当一个类实现了Serializable接口(该接口仅为标记接口,不包含任何方法定义),表示该类可以序列化.序列化的目的是将一个实现了Serializable接口的对象转换成一个字节序列,可以。

把该字节序列保存起来(例如:保存在一个文件里),以后可以随时将该字节序列恢复为原来的对象。甚至可以将该字节序列放到其他计算机上或者通过网络传输到其他计算机上恢复,只要该计

算机平台存在相应的类就可以正常恢复为原来的对象。

实现:要序列化一个对象,先要创建某些OutputStream对象,然后将其封装在一个ObjectOutputStream对象内,再调用writeObject()方法即可序列化一个对象;反序列化也类似。
import java.io.*;

public class Person implements Serializable {
private String userName;
private String password;

public Person(String userName, String password) {
this.userName = userName;
this.password = password;
}

public String toString() {
return "userName:" + userName + "  password:" + password;
}

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//序列化一个对象(存储到一个文件)
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));
oos.writeObject("Save a object:\n");
oos.writeObject(new Person("Bruce", "123456"));
oos.close();

//反序列化,将该对象恢复(存储到一个文件)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));
String s = (String)ois.readObject();
Person p = (Person)ois.readObject();
System.out.println(s + p);

//序列化一个对象(存储到字节数组)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(baos);
oos2.writeObject("Save another object:\n");
oos2.writeObject(new Person("Phil", "654321"));
oos2.close();

//反序列化,将该对象恢复(存储到字节数组)
ObjectInputStream ois2 = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
s = (String)ois2.readObject();
p = (Person)ois2.readObject();
System.out.println(s + p);
}
}
//输入如下信息
Save a object:
userName:Bruce  password:123456
Save another object:
userName:Phil  password:654321

transient关键字:
自动序列化将对象的所有字段都持久化了,有时候需要对某些字段不进行自动化(如密码,因为序列化会暴光密码信息),这个时候可以使用transient关键字(只能和Serializable对象一起使

用),其作用是不序列化某些字段。将Person类的字段改为如下定义,再运行上面的程序:
private String userName;
private transient String password;
//输入如下信息
Save a object:
userName:Bruce  password:null
Save another object:
userName:Phil  password:null

控制序列化字段,甚至该字段是被transient修饰的字段也能将其序列化。手动序列化需要添加两个私有(private)方法(writeObject()和readObject()),在该私有方法中控制序列花字段。
import java.io.*;

public class Person implements Serializable {
private String userName;
private transient String password;

public Person(String userName, String password) {
this.userName = userName;
this.password = password;
}

public String toString() {
return "userName:" + userName + "  password:" + password;
}

private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();  //序列化所有非transient字段,必须是该方法的第一个操作
out.writeObject(password); //序列化transient字段
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();             //反序列化所有非transient字段,必须是该方法的第一个操作
password = (String)in.readObject(); //反序列化transient字段
}

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//序列化一个对象(存储到一个文件)
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));
oos.writeObject("Save a object:\n");
oos.writeObject(new Person("Bruce", "123456"));
oos.close();

//反序列化,将该对象恢复(存储到一个文件)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));
String s = (String)ois.readObject();
Person p = (Person)ois.readObject();
System.out.println(s + p);
}
}
//输入如下信息
Save a object:
userName:David  password:13579

控制序列化字段还可以使用Externalizable接口替代Serializable借口。此时需要定义一个默认构造器,否则将为得到一个异常(java.io.InvalidClassException: Person; Person; no

valid constructor);还需要定义两个方法(writeExternal()和readExternal())来控制要序列化的字段。
import java.io.*;

public class Person implements Externalizable {
private String userName;
private String password;

public Person() {
System.out.println("default constructor invoked!");
}

public Person(String userName, String password) {
this.userName = userName;
this.password = password;
}

public String toString() {
return "userName:" + userName + "  password:" + password;
}

public void writeExternal(ObjectOutput out) throws IOException {
//序列化字段
out.writeObject(userName);
out.writeObject(password);
}

public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
//反序列化字段
userName = (String)in.readObject();
password = (String)in.readObject();
}

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//序列化一个对象(存储到一个文件)
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));
oos.writeObject("Save a object:\n");
oos.writeObject(new Person("Leo", "1984"));
oos.close();

//反序列化,将该对象恢复(存储到一个文件)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));
String s = (String)ois.readObject();
Person p = (Person)ois.readObject();
System.out.println(s + p);
}
}
//输入如下信息
default constructor invoked!
Save a object:
userName:Leo  password:1984

以上方式只能恢复成Java对象,如果想要恢复成其他对象(如C++对象),那就要将Java对象转换为XML格式,这样可以使其被各种平台和各种语言使用。可以使用随JDK一起发布的javax.xam.*类库,或者使用开源XOM类库(可以从www.xom.nu下载并获得文档)。
分享到:
评论

相关推荐

    Android序列化——Serializable与Parcelable

    Serializable是Java提供的一个接口,它是最简单也最常用的序列化方式。只需让类实现Serializable接口,系统就会自动处理序列化和反序列化。使用`writeObject()`和`readObject()`方法可以自定义序列化的行为。 优点...

    hessian学习基础篇——序列化和反序列化

    在Java中,如果一个类实现了Serializable接口,那么该类的对象就可以被序列化。序列化的目的是为了保存对象的状态以便后续使用或在网络上传输。 Hessian,由Caucho Technology开发,是一种二进制的序列化格式。相比...

    一个Java序列化反序列化库,用于将Java对象转换为JSON和返回JSON.zip

    Java序列化和反序列化是Java开发中常见且重要的概念,它们主要用于对象的状态持久化以及在不同系统间传递数据。本库专注于将Java对象转换为JSON格式,这在Web服务、API开发、数据存储和传输等方面都有广泛的应用。...

    Java反序列化回显解决方案.docx

    Java序列化是指将对象的状态信息转换为可以存储或传输的形式的过程。相反,反序列化则是在适当的时候把这个流转换回原对象的过程。当应用程序接收来自不受信任源的数据并进行反序列化时,可能触发安全漏洞。例如,...

    java反射机制 字符串——java对象

    在Java中,将Java对象的数据封装成XML格式的字符串,通常涉及到对象序列化的过程。对象序列化是将对象的状态转换为字节流,以便存储或在网络上传输。这个过程可以通过实现`java.io.Serializable`接口来完成。反序列...

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

    Java序列化是一项核心功能,它允许程序员将对象的状态转化为字节流的形式,从而实现对象的持久化存储或者在网络之间进行传递。这对于诸如远程方法调用(RMI)、分布式计算、对象存储以及缓存管理等场景至关重要。下面...

    java的课程设计——聊天器 有代码和论文

    Java提供了Serializable接口,实现了这个接口的对象可以通过ObjectOutputStream进行序列化,然后通过ObjectInputStream在另一端进行反序列化,从而实现数据的交换。 此外,为了提升用户体验,聊天器可能还会涉及到...

    JAVA的对象永续之道

    Java的对象永续之道,主要探讨了Java中对象的持久化技术——序列化(serialization)的原理与实践。在计算机科学中,对象的持久性是指将内存中的数据转换为持久存储形式,如硬盘上的文件,以便在系统重启后仍能保留...

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

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

    Java 笔试题————Java找工作的宝典

    - **对象序列化**:通过实现Serializable接口,可以将Java对象转换为字节流,便于存储和网络传输。 7. **网络编程** - **Socket编程**:Java提供了Socket和ServerSocket类进行网络通信,建立TCP连接。 - **URL和...

    关于Java您不知道的5件事

    - Java序列化是一种将Java对象的状态转换为字节数组的方法,以便于存储或在网络间传输。 - 序列化机制依赖于`java.io.ObjectInputStream`和`java.io.ObjectOutputStream`类,以及对象类实现了`Serializable`接口。...

    JAVA雇员管理系统——文件形式

    2. **数据序列化与反序列化**:为了持久化雇员对象,JAVA提供了`Serializable`接口。实现这个接口的对象可以通过`ObjectOutputStream`写入文件,然后通过`ObjectInputStream`读取。这样可以将对象的状态保存到磁盘并...

    Java 的对象永续之道

    当一个类实现了`Serializable`接口后,Java的序列化机制就能处理这个类的对象。 - **自定义序列化**:在某些情况下,开发者可能需要更精细地控制序列化的过程。可以通过实现`Externalizable`接口来自定义序列化逻辑...

    android 序列化1

    本文主要讨论Android特有的序列化方式——`Parcelable`接口,以及它与Java标准序列化`Serializable`接口的区别。 `Parcelable`接口是Android框架提供的一种高效的数据序列化方式,主要用于那些需要频繁在内存、...

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

    Java提供了一种机制,允许对象实现 `Serializable` 接口后自动完成序列化过程。对于需要更精确控制序列化的对象,可以实现 `Externalizable` 接口。 - **`Serializable` 接口**:这是一个标记接口,没有方法定义。...

    java反序列化漏洞利用

    Java反序列化漏洞利用是Java安全领域中的一个重要话题,它涉及到程序执行流程中的一个环节——序列化与反序列化。序列化是将对象的状态转换为字节流的过程,便于存储或网络传输;反序列化则是将字节流恢复为对象的...

    基于Java的存储与读取对象.zip

    Java序列化是将对象的状态转换为字节流的过程,以便可以存储在磁盘上或者在网络上传输。要使一个类可序列化,你需要让该类实现`java.io.Serializable`接口。例如: ```java public class MyObject implements ...

    Java实习报告——山寨QQ聊天工具设计

    这个类实现了Serializable接口,确保消息能在网络间进行序列化传输。 - **代码②**:MessageType枚举类定义了消息类型的常量,例如LOGIN_MESSAGE(登录消息)和TEXT_MESSAGE(文本消息),便于在程序中识别和处理不同...

    JedisSerialization:实现利用Jedis向Redis中写入和得到Java对象的几种序列化工具:JDK、XML、JSON、Protostuff

    JDK提供了一种内置的序列化机制,通过实现`Serializable`接口使类可以被序列化。在写入Redis时,可以使用`ObjectOutputStream`将Java对象转换为字节数组,然后通过Jedis的`set`方法存入Redis。反序列化时,使用`...

    Intent传递对象

    本篇文章将深入探讨如何通过Intent传递对象,以及涉及到的序列化方式——Serializable和Parcelable。 首先,Intent主要分为显式Intent和隐式Intent。显式Intent明确指定要启动的目标组件,而隐式Intent则通过ACTION...

Global site tag (gtag.js) - Google Analytics