http://developer.51cto.com/art/200908/147650.htm
http://developer.51cto.com/art/201104/253112.htm
对象序列化就是把对象写入到输出流中,用来存储或者传输。
对象的反序列化就是从输入流中读取对象。
要序列化的对象应该实现Serializable接口。
Serializable接口是一个标识接口,没有抽象方法。
Serializable有一个子接口Externalizable,实现Externalizable接口的类可以自行控制对象序列化荷反序列化过程。
一般来说,没有必要自己实现序列化接口,直接交给Java虚拟机是上策。
实现了序列化接口的类,如果其成员不需要序列化进去,则使用transient关键字进行修饰。
下面给出个例子:
import java.io.*;
/**
* Java对象的序列化测试
* File: ObjectStreamTest.java
* User: leizhimin
* Date: 2008-3-12 20:41:43
*/
public class ObjectStreamTest {
public static void main(String args[]) {
testObjectSeri();
testObjectInSeri();
}
/**
* 对象序列化测试
*/
public static void testObjectSeri() {
Person person = new Person("熔岩", "341022225562156", "lavasoft");
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("Q:\\study\\java5study\\src\\io\\person.dat");
oos = new ObjectOutputStream(fos);
oos.writeObject(person);
} catch (FileNotFoundException e) {
System.out.println("找不到指定的文件!");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oos.flush();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 对象反序列化测试
*/
public static void testObjectInSeri() {
FileInputStream fis = null;
ObjectInputStream ois = null;
Person person = null;
try {
fis = new FileInputStream("Q:\\study\\java5study\\src\\io\\person.dat");
ois = new ObjectInputStream(fis);
person = (Person) ois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(person.toString());
}
}
/**
* 测试序列化所用的类
*/
class Person implements Serializable {
private String username;
private String cardNumber;
private transient String password;
public Person(String username, String cardNumber, String password) {
this.username = username;
this.cardNumber = cardNumber;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getCardNumber() {
return cardNumber;
}
public void setCardNumber(String cardNumber) {
this.cardNumber = cardNumber;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String toString() {
StringBuffer sb = new StringBuffer(this.getClass().getName());
sb.append("[");
sb.append("\n\t");
sb.append("username=" + this.username);
sb.append("\n\t");
sb.append("cardNumber=" + this.cardNumber);
sb.append("\n\t");
sb.append("password=" + this.password);
sb.append("]");
return sb.toString();
}
}
运行结果为:
io.Person[
username=熔岩
cardNumber=341022225562156
password=null]
Process finished with exit code 0
属性password=null,说明在序列化过程中忽略了。
说到此,还有一个容易忽略的问题--serialVersionUID :
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致
InvalidClassException
。可序列化类可以通过声明名为
"serialVersionUID"
的字段(该字段必须是静态 (static)、最终 (final) 的
long
型字段)显式声明其自己的 serialVersionUID:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java(TM) 对象序列化规范”中所述。不过,强烈建议 所有可序列化类都显式声明 serialVersionUID 值,原因计算默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的
InvalidClassException
。因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议使用
private
修改器显示声明 serialVersionUID(如果可能),原因是这种声明仅应用于立即声明类 -- serialVersionUID 字段作为继承成员没有用处。
serialVersionUID 在Eclipse里可以自动生成,可是在其他大部分IDE工具里面都不能自动生成。但是这个long型值取多少,心里没底,与其写还不如不写。
分享到:
相关推荐
以下是关于Java序列化机制和原理的详细解释: 1. **序列化接口**: Java中的序列化是通过实现`Serializable`接口来实现的。这个接口没有任何方法,它的存在仅仅是为了标记一个类可以被序列化。如以下示例所示: `...
首先,我们需要创建一个实现了`Serializable`接口的类`TestSerial`,这样Java序列化机制才能处理这个类的对象。 接下来,我们编写代码将对象序列化并输出为字节流,存储在一个临时文件`temp.out`中。 ```java ...
序列化机制是Java提供的强大工具之一,可以帮助开发者轻松地保存和恢复对象的状态。 #### 二、序列化的应用场景 1. **文件保存**:当需要将内存中的对象状态保存到文件中或数据库中时,序列化非常有用。 2. **网络...
Java序列化是Java平台中的一种标准机制,它允许将对象的状态转换为字节流,以便存储、传输或恢复。在Java中,一个类如果要实现序列化,需要实现`Serializable`接口,这是一个标记接口,不包含任何方法。下面我们将...
在给定的链接"Java序列化机制(2)- serialVersionUID 实验"中,博主通过一个实验详细解释了`serialVersionUID`的作用和重要性。实验可能包括以下步骤: 1. 创建一个实现`Serializable`接口的简单类,并运行序列化...
序列化ID,即`serialVersionUID`,是Java序列化机制中一个关键的概念。它是一个类的唯一标识符,用于在序列化和反序列化过程中确定类的版本一致性。如果序列化对象和反序列化对象的`serialVersionUID`不匹配,将会抛...
**FST:快速Java序列化的替代方案** 在Java开发中,序列化是一个常见的需求,它允许将对象的状态转换为字节流,以便于存储或网络传输。标准的Java序列化虽然方便,但在处理大量数据时,性能往往成为瓶颈。这时,FST...
总的来说,protobuf是Java序列化的一个强大工具,尤其在处理大量数据交换和跨平台通信时,它的效率和灵活性使它成为首选。学习和掌握protobuf不仅可以提升项目性能,还能提高代码的可维护性和扩展性。
Java序列化机制是Java平台提供的一种标准方法,用于将对象的状态转换为字节序列,以便在网络中传输或存储在磁盘、数据库等持久化介质中。这一机制在分布式环境、远程通信、持久化存储和数据交换等多个场景下具有广泛...
此外,还将深入讨论如何精准控制序列化机制,帮助读者在实际编程中正确运用Java序列化技术,避免常见误区,并掌握高效利用该技术的方法。 **关键词:** 序列化(Serialize)、反序列化(DeSerialize)、类加载...
Java对象序列化是Java平台提供的一种机制,允许将对象的状态转换为字节流,以便存储在磁盘上、通过网络传输或在不同时间点恢复。这个过程涉及到将一个复杂的Java对象模型转换为简单的二进制表示,使得数据可以在不同...
标签中的“源码”提示我们,了解这些序列化机制的内部工作原理,查看源代码可以帮助我们更深入地理解其优化点和可能的改进空间。“工具”则意味着除了理论知识,还有实际可用的库和工具可以帮助我们在项目中实施这些...
管理系统源码.zip、README.txt 在本项目中,“学生管理系统(序列化和反序列化)”是一个基于Java或类似编程语言实现的系统,其核心功能是...在开发类似的系统时,理解并掌握序列化和反序列化的核心原理是非常重要的。
3. **Protobuf**: Google的协议缓冲区,提供高效的序列化机制,适用于网络通信和数据存储,具有较小的体积和更快的速度。 四、反序列化安全问题 1. **代码执行漏洞**: 不安全的反序列化可能导致远程代码执行。攻击...
1. **Java序列化机制**:Java对象序列化是通过实现`Serializable`接口来标记一个类可被序列化。`ObjectOutputStream`用于将对象写入流,`ObjectInputStream`用于从流中读取并反序列化对象。 2. **易受攻击的库**:...
接下来,我们讨论Parcelable,这是Android特有的序列化机制,主要用于内存中的对象传输,例如在Activity之间传递数据或者保存到Bundle中。相比于Serializable,Parcelable提供了更高的性能和更低的内存消耗。实现...
JAVA序列化和反序列化的底层实现原理解析 一、基本概念 JAVA序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程。序列化是把对象转换成有序字节流,以便在网络上传输...
Java序列化不仅仅是对数据的简单编码,更重要的是它涉及到对象的生命周期和状态的保存。 要实现对象的序列化,Java对象必须实现`Serializable`接口。这是一个特殊的标识接口,不包含任何方法,它的作用仅仅是标记一...