友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
狗狗书籍 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第146章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




—只能认为这是序列化机制玩的一个把戏。  

在任何情况下,接口中的定义的任何东西都会自动具有public 属性,所以假若writeObject()和 

readObject()必须为 private,那么它们不能成为接口(interface)的一部分。但由于我们准确地加上了签 

名,所以最终的效果实际与实现一个接口是相同的。  

看起来似乎我们调用ObjectOutputStream。writeObject()的时候,我们传递给它的Serializable 对象似乎 

会被检查是否实现了自己的writeObject() 。若答案是肯定的是,便会跳过常规的序列化过程,并调用 

writeObject() 。readObject()也会遇到同样的情况。  

还存在另一个问题。在我们的writeObject() 内部,可以调用defaultWriteObject(),从而决定采取默认的 

writeObject()行动。类似地,在 readObject()内部,可以调用defaultReadObject()。下面这个简单的例子 

演示了如何对一个 Serializable 对象的存储与恢复进行控制:  

  

//: SerialCtl。java  

// Controlling serialization by adding your own  



                                                                                       324 


…………………………………………………………Page 326……………………………………………………………

// writeObject() and readObject() methods。  

import java。io。*;  

  

public class SerialCtl implements Serializable {  

  String a;  

  transient String b;  

  public SerialCtl(String aa; String bb) {  

    a = 〃Not Transient: 〃 + aa;  

    b = 〃Transient: 〃 + bb;  

  }  

  public String toString() {  

    return a + 〃n〃 + b;  

  }  

  private void   

    writeObject(ObjectOutputStream stream)  

      throws IOException {  

    stream。defaultWriteObject();  

    stream。writeObject(b);  

  }  

  private void   

    readObject(ObjectInputStream stream)  

      throws IOException; ClassNotFoundException {  

    stream。defaultReadObject();  

    b = (String)stream。readObject();  

  }  

  public static void main(String'' args) {  

    SerialCtl sc =   

      new SerialCtl(〃Test1〃; 〃Test2〃);  

    System。out。println(〃Before: n〃 + sc);  

    ByteArrayOutputStream buf =   

      new ByteArrayOutputStream();  

    try {  

      ObjectOutputStream o =  

        new ObjectOutputStream(buf);  

      o。writeObject(sc);  

      // Now get it back:  

      ObjectInputStream in =  

        new ObjectInputStream(  

          new ByteArrayInputStream(  

            buf。toByteArray()));  

      SerialCtl sc2 = (SerialCtl)in。readObject();  

      System。out。println(〃After:n〃 + sc2);  

    } catch(Exception e) {  

      e。printStackTrace();  

    }  

  }  

} ///:~  

  

在这个例子中,一个String 保持原始状态,其他设为transient (临时),以便证明非临时字段会被 

defaultWriteObject()方法自动保存,而 transient 字段必须在程序中明确保存和恢复。字段是在构建器内 

部初始化的,而不是在定义的时候,这证明了它们不会在重新装配的时候被某些自动化机制初始化。  

若准备通过默认机制写入对象的非 transient 部分,那么必须调用defaultWriteObject(),令其作为 



                                                                                          325 


…………………………………………………………Page 327……………………………………………………………

writeObject() 中的第一个操作;并调用defaultReadObject(),令其作为 readObject()的第一个操作。这些 

都是不常见的调用方法。举个例子来说,当我们为一个ObjectOutputStream 调用defaultWriteObject()的 

时候,而且没有为其传递参数,就需要采取这种操作,使其知道对象的句柄以及如何写入所有非transient 

的部分。这种做法非常不便。  

transient 对象的存储与恢复采用了我们更熟悉的代码。现在考虑一下会发生一些什么事情。在 main()中会 

创建一个SerialCtl 对象,随后会序列化到一个ObjectOutputStream 里(注意这种情况下使用的是一个缓冲 

区,而非文件——与ObjectOutputStream 完全一致)。正式的序列化操作是在下面这行代码里发生的:  

o。writeObject(sc);  

其中,writeObject()方法必须核查 sc,判断它是否有自己的writeObject()方法(不是检查它的接口——它 

根本就没有,也不是检查类的类型,而是利用反射方法实际搜索方法)。若答案是肯定的,就使用那个方 

法。类似的情况也会在 readObject()上发生。或许这是解决问题唯一实际的方法,但确实显得有些古怪。  

  

3。 版本问题  

有时候可能想改变一个可序列化的类的版本(比如原始类的对象可能保存在数据库中)。尽管这种做法得到 

了支持,但一般只应在非常特殊的情况下才用它。此外,它要求操作者对背后的原理有一个比较深的认识, 

而我们在这里还不想达到这种深度。JDK 1。1 的HTML 文档对这一主题进行了非常全面的论述(可从Sun 公司 

下载,但可能也成了Java 开发包联机文档的一部分)。  



10。9。3 利用“持久性”  



一个比较诱人的想法是用序列化技术保存程序的一些状态信息,从而将程序方便地恢复到以前的状态。但在 

具体实现以前,有些问题是必须解决的。如果两个对象都有指向第三个对象的句柄,该如何对这两个对象序 

列化呢?如果从两个对象序列化后的状态恢复它们,第三个对象的句柄只会出现在一个对象身上吗?如果将 

这两个对象序列化成独立的文件,然后在代码的不同部分重新装配它们,又会得到什么结果呢?  

下面这个例子对上述问题进行了很好的说明:  

  

//: MyWorld。java  

import java。io。*;  

import java。util。*;  

  

class House implements Serializable {}  

  

class Animal implements Serializable {  

  String name;  

  House preferredHouse;  

  Animal(String nm; House h) {   

    name = nm;   

    preferredHouse = h;  

  }  

  public String toString() {  

    return name + 〃'〃 + super。toString() +   

      〃'; 〃 + preferredHouse + 〃n〃;  

  }  

}  

  

public class MyWorld {  

  public static void main(String'' args) {  

    House house = new House();  

    Vector  animals = new Vector();  

    animals。addElement(  

      new Animal(〃Bosco the dog〃; house));  

    animals。addElement(  

      new Animal(〃Ralph the hamster〃; house));  



                                                                                        326 


…………………………………………………………Page 328……………………………………………………………

    animals。addElement(  

      new Animal(〃Fronk the cat〃; house));  

    System。out。println(〃animals: 〃 + animals);  

  

    try {  

      ByteArrayOutputStream buf1 =   

        new ByteArrayOutputStream();  

      ObjectOutputStream o1 =  

        new ObjectOutputStream(buf1);  

      o1。writeObject(animals);  

      o1。writeObject(animals); // Write a 2nd set  

      // Write to 
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!