对象有状态和行为两种属性。行为存在于类中,而状态存在于个别的对象中。存储状态的选择有很多种,这可能要看你如何使用存储下来的状态而决定。下面我们讨论两种选项:
        如果只有自己写的Java程序会用到这些数据:用序列化(Serialization)
        如果数据需要被其他程序引用:写一个纯文本文件。用其他程序可以解析的特殊字符写到文件中。譬如:tab
        
序列化的文件是很难让一般人阅读的,但它比纯文本文件更容易让程序恢复对象的状态,也比较安全。
        当然还有其他的选择。你可以将数据存进任何格式中。
        
对象序列化的步骤:
        1.创建出FileOutputStream
            FileOutputStream fileStream = new FileOutputStream("MyGame.ser");
        2.创建出ObjectOutputStream
            ObjectOutputStream os = new ObjectOutputStream(fileStream);
        3.写入对象
            os.writeObject(characterOne);
            os.writeObject(characterTwo);
            os.writeObject(characterThree);
        4.关闭ObjectOutputStream
            os.close();
        
        Java的输入/输出API带有
连接类型的串流,它代表来源与目的地之间的连接,连接串流将串流与其他串流连接起来。
        一般来说,串流要两两连接才能做出有意义的事情--其中一个表示连接,另一个则是要被调用方法的。为何要两个?因为连接的串流通常都是很低层的。以FileOutputStream为例,它有可以写入字节的方法。但我们通常不会直接写字节,而是以对象层次的观点来写入,所以需要高层的连接串流。那为何不以单一的串流来执行呢?这就要考虑到良好的面向对象设计了。每个类只要做好一件事。FileOutputStream把字节写入文件。ObjectOutputStream把对象转换成可以写入串流的数据。当我们调用ObjectOutputStream的writeObject方法时,对象会被打成串流送到FileOutputStream来写入文件。
        
对象序列化的时候发生了什么事?
        对象实例变量的值及Java虚拟机所需的信息被保存下来。
        
对象的状态是什么?有什么需要保存?
        当对象被序列化时,被该对象引用的实例变量也会被序列化。且所有被引用的对象也会被序列化……最棒的是,这些操作都是自动的。
        
如果要让类能够被序列化,就实现Serializable接口
        Serializable接口又被称为marker或tag类的标记用接口,因为此接口并没有任何方法需要实现的[
备注:该接口没有任何变量及方法]。它的唯一目的就是声明实现它的类是可以被序列化的。[关于该接口的介绍:
http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/io/Serializable.html]
        例子:
                import java.io.*;
                public class Box 
implements Serializable{
                        
                }
        整个对象版图都必须正确地序列化,不然就得全部失败。如果某个实例变量不能或不应该被序列化,就把它标记为transient(瞬时)的。
       
 
        解序列化:还原对象
                序列化的反向操作。
        步骤如下:
         1.创建FileInputStream
         FileInputStream fileStream = new FileInputStream("MyGame.ser");
         2.创建ObjectInputStream
         ObjectInputStream os = new ObjectInputStream(fileStream);
         3.读取对象
         Object one = os.readObject();
         Object two = os.readObject();
         Object three = os.readObject();
         4.转换对象类型
          GameCharacter elf = (GameCharacter) one;
          GameCharacter troll = (GameCharacter) two;
          GameCharacter magician = (GameCharacter) three;
         5.关闭
          os.close();
         
解序列化时发生了什么?
         当对象被解序列化时,Java虚拟机会通过尝试在堆上创建新的对象,让它维持与被序列化时有相同的状态来恢复对象的原态。但这当然不包括transient的变量,它们不是null便是使用primitive主数据类型的默认值。
         具体过程如下:
         1.对象从Stream中读出来
         2.Java虚拟机通过存储的信息判断出对象的class类型
         3.Java虚拟机尝试查找和加载对象的类。如果找不到或者无法加载该类,则会抛出异常。
         4.新的对象会被配置在堆上,但构造函数不会执行。
         5.如果该对象在继承树上有个不可序列化的祖先类,则该不可序列化类以及在它之上的类的构造函数就会执行。
         6.对象的实例变量会被还原成序列化时点的状态值。
         
        
 静态变量会被序列化么?[no]
         下面列出一个完整例子来展示序列化以及反序列化:
          
         
 1 package serial;
package serial;
 2
 3 import java.io.Serializable;
import java.io.Serializable;
 4
 5
 /** *//**
/** *//**
 6 *
 *
 7 * @author Administrator
 * @author Administrator
 8 */
 */
 9
 public class GameCharacter implements Serializable {
public class GameCharacter implements Serializable {
10
11 int power;
    int power;
12 String type;
    String type;
13 String[] weapons;
    String[] weapons;
14
15
 public GameCharacter(int p, String t, String[] w) {
    public GameCharacter(int p, String t, String[] w) {
16 this.power = p;
        this.power = p;
17 this.type = t;
        this.type = t;
18 this.weapons = w;
        this.weapons = w;
19 }
    }
20
21
 public int getPower() {
    public int getPower() {
22 return power;
        return power;
23 }
    }
24
25
 public String getType() {
    public String getType() {
26 return type;
        return type;
27 }
    }
28
29
 public String getWeapons() {
    public String getWeapons() {
30 String weaponsList = "";
        String weaponsList = "";
31
 for (int i = 0; i < weapons.length; i++) {
        for (int i = 0; i < weapons.length; i++) {
32 weaponsList += weapons[i] + " ";
            weaponsList += weapons[i] + " ";
33 }
        }
34 return weaponsList;
        return weaponsList;
35 }
    }
36 }
}
37
 
 1 package serial;
package serial;
 2
 3 import java.io.FileInputStream;
import java.io.FileInputStream;
 4 import java.io.FileOutputStream;
import java.io.FileOutputStream;
 5 import java.io.IOException;
import java.io.IOException;
 6 import java.io.ObjectInputStream;
import java.io.ObjectInputStream;
 7 import java.io.ObjectOutputStream;
import java.io.ObjectOutputStream;
 8
 9
 /** *//**
/** *//**
10 *
 *
11 * @author Administrator
 * @author Administrator
12 */
 */
13
 public class GameSaverTest {
public class GameSaverTest {
14
15
 public static void main(String[] args) {
    public static void main(String[] args) {
16
 GameCharacter one = new GameCharacter(50, "Elf", new String[]{"bow", "sword", "dust"});
        GameCharacter one = new GameCharacter(50, "Elf", new String[]{"bow", "sword", "dust"});
17
 GameCharacter two = new GameCharacter(50, "Troll", new String[]{"bare hands", "big ax"});
        GameCharacter two = new GameCharacter(50, "Troll", new String[]{"bare hands", "big ax"});
18
 GameCharacter three = new GameCharacter(50, "Magician", new String[]{"spells", "invisibility"});
        GameCharacter three = new GameCharacter(50, "Magician", new String[]{"spells", "invisibility"});
19
20
 try {
        try {
21 //将one, two, three序列化到storage.ser
            //将one, two, three序列化到storage.ser
22 FileOutputStream fileStream = new FileOutputStream("storage.ser");
            FileOutputStream fileStream = new FileOutputStream("storage.ser");
23 ObjectOutputStream os = new ObjectOutputStream(fileStream);
            ObjectOutputStream os = new ObjectOutputStream(fileStream);
24 os.writeObject(one);
            os.writeObject(one);
25 os.writeObject(two);
            os.writeObject(two);
26 os.writeObject(three);
            os.writeObject(three);
27 os.close();
            os.close();
28
 } catch (IOException ex) {
        } catch (IOException ex) {
29 ex.printStackTrace();
            ex.printStackTrace();
30 }
        }
31 one = null;
        one = null;
32 two = null;
        two = null;
33 three = null;
        three = null;
34
 try {
        try {
35 //从storage.ser中按照序列化的顺序读取出one, two, three
            //从storage.ser中按照序列化的顺序读取出one, two, three
36 FileInputStream fileInputStream = new FileInputStream("storage.ser");
            FileInputStream fileInputStream = new FileInputStream("storage.ser");
37 ObjectInputStream is = new ObjectInputStream(fileInputStream);
            ObjectInputStream is = new ObjectInputStream(fileInputStream);
38 one = (GameCharacter) is.readObject();
            one = (GameCharacter) is.readObject();
39 two = (GameCharacter) is.readObject();
            two = (GameCharacter) is.readObject();
40 three = (GameCharacter) is.readObject();
            three = (GameCharacter) is.readObject();
41 System.out.println(one.type);
            System.out.println(one.type);
42 System.out.println(two.type);
            System.out.println(two.type);
43 System.out.println(three.type);
            System.out.println(three.type);
44 is.close();
            is.close();
45
46
 } catch (Exception ex) {
        } catch (Exception ex) {
47 ex.printStackTrace();
            ex.printStackTrace();
48 }
        }
49 }
    }
50 }
}
51
52
 
        此处为了简洁起便,抛出最顶层异常。
        运行结果如下:
        run:
        Elf
        Troll
        Magician
        成功生成(总时间:1 秒)
        在工程目录下,能看到“storage.ser”这个文件。用记事本打开,可看到以下内容:
 sr serial.GameCharacter恃83rV I powerL typet Ljava/lang/String;[ weaponst [Ljava/lang/String;xp   2t Elfur [Ljava.lang.String;V玳{G  xp   t bowt swordt dustsq ~     2t Trolluq ~    t 
bare handst big axsq ~     2t Magicianuq ~    t spellst invisibility