- 我们可以通过序列化来保存一个对象的状态(实例变量)到文件中,也可以从这个格式化的文件中很容易地读取对象的状态从而可以恢复我们保存的对象。
-
我们可以通过序列化来保存一个对象的状态(实例变量)到文件中,也可以从这个格式化的文件中很容易地读取对象的状态从而可以恢复我们保存的对象。
对象序列化就是把对象写入到输出流中,用来存储或者传输。
对象的反序列化就是从输入流中读取对象。
用来实现序列化的类都在java.io包中,我们常用的类或接口有:
ObjectOutputStream:提供序列化对象并把其写入流的方法
ObjectInputStream:读取流并反序列化对象
Serializable:一个对象想要被序列化,那么它的类就要实现 此接口,这个对象的所有属性(包括private属性、包括其引用的对象)都可以被序列化和反序列化来保存、传递。
Externalizable:他是Serializable接口的子类,有时我们不希望序列化那么多,可以使用这个接口,这个接口的writeExternal()和readExternal()方法可以指定序列化哪些属性;
但是如果你只想隐藏一个属性,比如用户对象user的密码pwd,如果使用Externalizable,并除了pwd之外的每个属性都写在writeExternal()方法里,这样显得麻烦,可以使用Serializable接口,并在要隐藏的属性pwd前面加上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();
- }
- }
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
io.Person[ username=熔岩 cardNumber=341022225562156 password=null] Process finished with exit code 0
Serializable接口和Externalizable接口的区别不仅限于此:
Serializable序列化时不会调用默认的构造器,而Externalizable序列化时会调用默认构造器的!!!
其他说明:
1、 基本类型 的数据可以直接序列化
2、 对象要被序列化,它的类必须要实现Serializable接口;如果一个类中有引用类型的实例变量,这个引用类型也要实现Serializable接口。比如上面 的例子中,Student类中有一个Book类型 的实例就是,要想让Student的对象成功序列化,那么Book也必须要实现Serializable接口;
如果不想让Book实现Serializable接口,并且让Student类成功序列化也可以,使用transient关键字。
serialVersionUID作用:序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。 有两种生成方式: 一个是默认的1L,比如:private static final long se...
serialVersionUID作用:
序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
有两种生成方式:
一个是默认的1L,比如:private static final long serialVersionUID = 1L;
一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;
当你一个类实现了Serializable接口,如果没有定义serialVersionUID,Eclipse会提供这个
提示功能告诉你去定义 。在Eclipse中点击类中warning的图标一下,Eclipse就会
自动给定两种生成的方式。如果不想定义它,在Eclipse的设置中也
可以把它关掉的,设置如下:
Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==>
Potential programming problems
将Serializable class without serialVersionUID的warning改成ignore即可。
最后,还有两个问题:
1、 如果一个类没有实现Serializable接口,但是它的基类实现 了,这个类可不可以序列化?
2、 和上面相反,如果一个类实现了Serializable接口,但是它的父类没有实现 ,这个类可不可以序列化?
第1个问题:一个类实现 了某接口,那么它的所有子类都间接实现了此接口,所以它可以被 序列化。
第2个问题:Object是每个类的超类,但是它没有实现 Serializable接口,但是我们照样在序列化对象,所以说明一个类要序列化,它的父类不一定要实现Serializable接口。但是在父类中定义 的状态能被正确 的保存以及读取吗?这个我将在下一篇文章中用一个例子来说明,请见http://blog.csdn.net/moreevan/article/details/6698529
第3个问题:如果将一个对象写入某文件(比如是a),那么之后对这个对象进行一些修改,然后把修改的对象再写入文件a,那么文件a中会包含该对象的两个 版本吗?
相关推荐
序列化的核心接口是 `java.io.Serializable`,它是一个标记接口,没有定义任何方法,用于标记可以被序列化的类。 #### 二、实现序列化的方法 为了使一个类支持序列化,需要让该类实现 `Serializable` 接口。实现这...
在 serializable-prj 项目中,可能包含了各种示例代码,展示了如何在Java中实现和使用序列化功能。 综上所述,Java的序列化和外部化是实现对象持久化和跨进程通信的关键技术。理解并熟练掌握这些概念,能够帮助...
另外,还有`java.io.Externalizable`接口,它继承自`Serializable`,但提供了更细粒度的控制权,允许类自定义序列化和反序列化的行为。如果一个类实现了`Externalizable`,则需要手动实现`writeExternal...
- **Externalizable**:继承自Serializable接口,提供更细粒度的控制,允许开发者自定义序列化和反序列化的行为。 4. **序列化和反序列化步骤** - **序列化**: - 创建`ObjectOutputStream`,可以传入一个其他...
- `Externalizable`: 允许对象自定义序列化和反序列化行为。 - `FileFilter`: 用于过滤文件。 - `FilenameFilter`: 用于过滤文件名。 - `ObjectInputValidation`: 用于验证反序列化的对象。 2. **类** - `...
总结来说,Java中的序列化和反序列化是通过`Serializable`接口和`Externalizable`接口来实现的。`Serializable`接口是默认的序列化方式,适用于大多数简单情况;而`Externalizable`接口则提供了自定义序列化行为的...
Java中的序列化和反序列化是...总之,Java的序列化和反序列化机制提供了一种方便的方式来持久化和传输对象,同时也允许开发者自定义序列化行为以满足特定需求。正确理解和应用这些机制对于Java开发者来说是至关重要的。
总结来说,Java对象序列化是将对象状态转换为字节流,便于存储和网络传输的关键技术。通过实现`Serializable`或`Externalizable`接口,我们可以控制对象如何被序列化和反序列化,同时`transient`关键字提供了保护...
在Java中,要实现一个对象的序列化,该类必须实现`java.io.Serializable`接口,这是一个标记接口,不包含任何方法。 1. **什么是序列化:** 序列化是将对象转换为字节序列的过程,这个字节序列可以被保存到磁盘、...
### Java序列化(Serializable)与反序列化详解 #### 序列化概念与应用场景 序列化是指将程序中的对象转换为一系列字节序列的过程,主要用于保存对象的状态以便将来使用或者在网络之间传输对象。Java提供了内置的...
Java文件序列化是Java平台中一种重要的数据存储和交换机制,它允许我们将对象的状态转换为字节流,以便可以保存到磁盘、网络传输或在内存中存储,然后在需要时将这些字节流恢复为原来的对象。这个过程称为序列化...
`Serializable`是一个标记接口,而`Externalizable`则提供了更精细的控制,允许开发者自定义序列化和反序列化的过程。 #### 实现对象序列化 实现序列化的基本步骤包括: 1. **实现接口**:使类实现`Serializable`...
`java.io.ObjectOutputStream`和`java.io.ObjectInputStream`是Java标准库中用于序列化和反序列化的类。前者通过`writeObject()`方法将对象写入输出流,后者通过`readObject()`方法从输入流中读取对象。 需要注意的...
序列化的实现依赖于`java.io.Serializable`接口。如果一个类想要支持序列化,只需让该类实现这个接口,无需提供任何方法。实现此接口后,Java的默认序列化机制会遍历对象的所有字段并将其写入字节流。请注意,静态...
在Java中,如果一个类需要支持序列化,那么这个类就需要实现`java.io.Serializable`接口,尽管该接口没有任何方法需要实现,但它的存在就标志着这个类的对象可以被序列化。 首先,我们来看一下`SerializableDemo`这...
Java中,对象的序列化主要涉及两个接口:`Serializable`和`Externalizable`。任何实现了`Serializable`接口的类的对象都可以被序列化,而`Externalizable`接口提供了更高级别的控制,允许类自定义其序列化和反序列化...
- **实现Serializable接口**:为了使一个对象可以被序列化,其对应的类必须实现`java.io.Serializable`接口。虽然该接口没有任何方法定义,但它作为一个标记接口存在。 - **序列化工具类**:Java提供了`java.io....
在Java中,如果一个对象需要被序列化,那么它的类必须实现java.io.Serializable接口。序列化的主要应用场景有:持久化对象、网络传输和多线程之间的通信。通过序列化,可以将对象转换为字节序列,然后写入磁盘或在...
为了支持序列化功能,Java定义了一个特殊的接口——`java.io.Serializable`,任何实现了这个接口的类都可以被序列化。 #### 序列化的过程 序列化的过程主要包括两个步骤:序列化和反序列化。 1. **序列化**:将...