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

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

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




是沿用老式的 InputStream 和OutputStream 结构。所以在一些特殊的场合下,不得不混合使用两种类型的层 

次结构。  



10。9。1 寻找类  



读者或许会奇怪为什么需要一个对象从它的序列化状态中恢复。举个例子来说,假定我们序列化一个对象, 

并通过网络将其作为文件传送给另一台机器。此时,位于另一台机器的程序可以只用文件目录来重新构造这 

个对象吗?  

回答这个问题的最好方法就是做一个实验。下面这个文件位于本章的子目录下:  

  

//: Alien。java  

// A serializable class  

import java。io。*;  

  

public class Alien implements Serializable {  

} ///:~  

  

用于创建和序列化一个 Alien 对象的文件位于相同的目录下:  

  

//: FreezeAlien。java  

// Create a serialized output file  

import java。io。*;  

  

public class FreezeAlien {  

  public static void main(String'' args)   

      throws Exception {  

    ObjectOutput out =   

      new ObjectOutputStream(  

        new FileOutputStream(〃file。x〃));  

    Alien zorcon = new Alien();  



                                                                                         318 


…………………………………………………………Page 320……………………………………………………………

    out。writeObject(zorcon);   

  }  

} ///:~  

  

该程序并不是捕获和控制违例,而是将违例简单、直接地传递到main()外部,这样便能在命令行报告它们。  

程序编译并运行后,将结果产生的 file。x 复制到名为 xfiles 的子目录,代码如下:  

  

//: ThawAlien。java  

// Try to recover a serialized file without the   

// class of object that's stored in that file。  

package c10。xfiles;  

import java。io。*;  

  

public class ThawAlien {  

  public static void main(String'' args)   

      throws Exception {  

    ObjectInputStream in =  

      new ObjectInputStream(  

        new FileInputStream(〃file。x〃));  

    Object mystery = in。readObject();  

    System。out。println(  

      mystery。getClass()。toString());  

  }  

} ///:~  

  

该程序能打开文件,并成功读取mystery 对象中的内容。然而,一旦尝试查找与对象有关的任何资料——这 

要求Alien 的Class 对象——Java 虚拟机(JVM)便找不到Alien。class (除非它正好在类路径内,而本例理 

应相反)。这样就会得到一个名叫 ClassNotFoundException 的违例(同样地,若非能够校验Alien 存在的证 

据,否则它等于消失)。  

恢复了一个序列化的对象后,如果想对其做更多的事情,必须保证JVM 能在本地类路径或者因特网的其他什 

么地方找到相关的。class文件。  



10。9。2  序列化的控制  



正如大家看到的那样,默认的序列化机制并不难操纵。然而,假若有特殊要求又该怎么办呢?我们可能有特 

殊的安全问题,不希望对象的某一部分序列化;或者某一个子对象完全不必序列化,因为对象恢复以后,那 

一部分需要重新创建。  

此时,通过实现Externalizable 接口,用它代替Serializable 接口,便可控制序列化的具体过程。这个 

Externalizable 接口扩展了 Serializable,并增添了两个方法:writeExternal()和readExternal()。在序 

列化和重新装配的过程中,会自动调用这两个方法,以便我们执行一些特殊操作。  

下面这个例子展示了Externalizable 接口方法的简单应用。注意Blip1 和Blip2 几乎完全一致,除了极微小 

的差别(自己研究一下代码,看看是否能发现):  

  

//: Blips。java  

// Simple use of Externalizable & a pitfall  

import java。io。*;  

import java。util。*;  

  

class Blip1 implements Externalizable {  

  public Blip1() {  

    System。out。println(〃Blip1 Constructor〃);  

  }  

  public void writeExternal(ObjectOutput out)  



                                                                                          319 


…………………………………………………………Page 321……………………………………………………………

      throws IOException {  

    System。out。println(〃Blip1。writeExternal〃);  

  }  

  public void readExternal(ObjectInput in)  

     throws IOException; ClassNotFoundException {  

    System。out。println(〃Blip1。readExternal〃);  

  }  

}  

  

class Blip2 implements Externalizable {  

  Blip2() {  

    System。out。println(〃Blip2 Constructor〃);  

  }  

  public void writeExternal(ObjectOutput out)  

      throws IOException {  

    System。out。println(〃Blip2。writeExternal〃);  

  }  

  public void readExternal(ObjectInput in)  

     throws IOException; ClassNotFoundException {  

    System。out。println(〃Blip2。readExternal〃);  

  }  

}  

  

public class Blips {  

  public static void main(String'' args) {  

    System。out。println(〃Constructing objects:〃);  

    Blip1 b1 = new Blip1();  

    Blip2 b2 = new Blip2();  

    try {  

      ObjectOutputStream o =  

        new ObjectOutputStream(  

          new FileOutputStream(〃Blips。out〃));  

      System。out。println(〃Saving objects:〃);  

      o。writeObject(b1);  

      o。writeObject(b2);  

      o。close();  

      // Now get them back:  

      ObjectInputStream in =  

        new ObjectInputStream(  

          new FileInputStream(〃Blips。out〃));  

      System。out。println(〃Recovering b1:〃);  

      b1 = (Blip1)in。readObject();  

      // OOPS! Throws an exception:  

//!   System。out。println(〃Recovering b2:〃);  

//!   b2 = (Blip2)in。readObject();  

    } catch(Exception e) {  

      e。printStackTrace();  

    }  

  }  

} ///:~  

  



                                                                                             320 


…………………………………………………………Page 322……………………………………………………………

该程序输出如下:  

Constructing objects:  

Blip1 Constructor  

Blip2 Constructor  

Saving objects:  

Blip1。writeExternal  

Blip2。writeExternal  

Recovering b1:  

Blip1 Constructor  

Blip1。readExternal  

  

未恢复Blip2 对象的原因是那样做会导致一个违例。你找出了 Blip1 和 Blip2 之间的区别吗?Blip1 的构建 

器是“公共的”(public),Blip2 的构建器则不然,这样便会在恢复时造成违例。试试将 Blip2 的构建器 

属性变成“public”,然后删除//!注释标记,看看是否能得到正确的结果。  

恢复b1 后,会调用 Blip1 默认构建器。这与恢复一个Serializable (可序列化)对象不同。在后者的情况 

下,对象完全以它保存下来的二进制位为基础恢复,不存在构建器调用。而对一个Externalizable 对象,所 

有普通的默认构建行为都会发生(包括在字段定义时的初始化),而且会调用readExternal()。必须注意这 

一事实——特别注意所有默认的构建行为都会进行——否则很难在自己的 Externalizable 对象中产生正确的 

行为。  

下面这个例子揭示了保存和恢复一个Externalizable 对象必须做的全部事情:  

  

//: Blip3。java  

// Reconstructing an externalizable object  

import java。io。*;  

import java。util。*;  

  

class Blip3 implements Externalizable {  

  int i;  

  String s; // No initialization  

  public Blip3() {  

    System。out。println(〃Blip3 Constructor〃);  

    // s; i not initialized  

  }  

  public Blip3(String x; int a) {  

    System。out。println(〃Blip3(String x; int a)〃);  

    s = x;  

    i = a;  

    // s & i initialized only in non…default  

    // constructor。  

  }  

  public String toString() { return s + i; }  

  public void writeExternal(ObjectOutput out)  

      throws IOException {  

    System。out。println(〃Blip3。writeExternal〃);  

    // You must do this:  

    out。writeObject(s); out。writeInt(i);  

  }  

  public void readExternal(ObjectInput in)  

     throws IOException; ClassNotFoundException {  

    System。out。println(〃Blip3。readExternal〃);  

    // You must do this:  

    s = (String)in。readObject();   



                                                                                          321 


…………………………………………………………Page 323……………………………………………………………

    i =in。readInt();  

  }  

  public static void main(String'' args) {  

    System。out。println(〃Constructing objects:〃);  

    Blip3 b3 = new Blip3(〃A String 〃; 47);  

    System。out。println(b3。toString());  

    try {  

      ObjectOutputStream o =  

        new ObjectOutputStream(  

          new FileOutputStream(〃Blip3。out〃));  

      System。out。println(〃Saving object:〃);  

      o。writeObject(b3);  

      o。close();  

      // Now get it back:  

      ObjectInputStream in =  

        new ObjectInputStream(  

          new FileInputStream(〃Blip3。out〃));  

      System。out。println(〃Recovering b3:〃) ;  

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