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

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

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





…………………………………………………………Page 599……………………………………………………………

        〃weight of 〃 +  

        // Using RTTI to get type  

        // information about the class:  

        t。getClass()。getName() +  

        〃 = 〃 + t。weight());  

    }  

    System。out。println(〃Total value = 〃 + val);  

  }  

  // Remainder of class provides support for  

  // prototyping:  

  public static class PrototypeNotFoundException  

      extends Exception {}  

  public static class CannotCreateTrashException  

      extends Exception {}  

  private static Vector trashTypes =   

    new Vector();  

  public static Trash factory(Info info)   

      throws PrototypeNotFoundException;   

      CannotCreateTrashException {  

    for(int i = 0; i 《 trashTypes。size(); i++) {  

      // Somehow determine the new type  

      // to create; and create one:  

      Class tc =   

        (Class)trashTypes。elementAt(i);  

      if (tc。getName()。indexOf(info。id) != …1) {  

        try {  

          // Get the dynamic constructor method  

          // that takes a double argument:  

          Constructor ctor =  

            tc。getConstructor(  

              new Class'' {double。class});  

          // Call the constructor to create a   

          // new object:  

          return (Trash)ctor。newInstance(  

            new Object''{new Double(info。data)});  

        } catch(Exception ex) {  

          ex。printStackTrace();  

          throw new CannotCreateTrashException();  

        }  

      }  

    }  

    // Class was not in the list。 Try to load it;  

    // but it must be in your class path!  

    try {  

      System。out。println(〃Loading 〃 + info。id);  

      trashTypes。addElement(  

        Class。forName(info。id));  

    } catch(Exception e) {  

      e。printStackTrace();  

      throw new PrototypeNotFoundException();  

    }  

    // Loaded successfully。 Recursive call   



                                                                                        598 


…………………………………………………………Page 600……………………………………………………………

    // should work this time:  

    return factory(info);  

  }  

  public static class Info {  

    public String id;  

    public double data;  

    public Info(String name; double data) {  

      id = name;  

      this。data = data;  

    }  

  }  

} ///:~  

  

基本Trash 类和 sumValue()还是象往常一样。这个类剩下的部分支持原型范式。大家首先会看到两个内部类 

 (被设为static 属性,使其成为只为代码组织目的而存在的内部类),它们描述了可能出现的违例。在它后 

面跟随的是一个Vector trashTypes,用于容纳 Class 句柄。  

在Trash。factory()中,Info 对象 id (Info 类的另一个版本,与前面讨论的不同)内部的 String 包含了要 

创建的那种 Trash 的类型名称。这个 String 会与列表中的Class 名比较。若存在相符的,那便是要创建的对 

象。当然,还有很多方法可以决定我们想创建的对象。之所以要采用这种方法,是因为从一个文件读入的信 

息可以转换成对象。  

发现自己要创建的Trash (垃圾)种类后,接下来就轮到“反射”方法大显身手了。getConstructor()方法 

需要取得自己的参数——由Class 句柄构成的一个数组。这个数组代表着不同的参数,并按它们正确的顺序 

排列,以便我们查找的构建器使用。在这儿,该数组是用 Java 1。1 的数组创建语法动态创建的:  

new Class'' {double。class}  

这个代码假定所有 Trash 类型都有一个需要 double 数值的构建器(注意 double。class 与 Double。class 是不 

同的)。若考虑一种更灵活的方案,亦可调用 getConstructors(),令其返回可用构建器的一个数组。  

从getConstructors()返回的是指向一个 Constructor 对象的句柄(该对象是 java。lang。reflect 的一部 

分)。我们用方法 newInstance() 动态地调用构建器。该方法需要获取包含了实际参数的一个Object 数组。 

这个数组同样是按 Java 1。1 的语法创建的:  

new Object'' {new Double(info。data)}  

在这种情况下,double 必须置入一个封装(容器)类的内部,使其真正成为这个对象数组的一部分。通过调 

用newInstance() ,会提取出 double,但大家可能会觉得稍微有些迷惑——参数既可能是 double,也可能是 

Double,但在调用的时候必须用Double 传递。幸运的是,这个问题只存在于基本数据类型中间。  

理解了具体的过程后,再来创建一个新对象,并且只为它提供一个Class 句柄,事情就变得非常简单了。就 

目前的情况来说,内部循环中的return 永远不会执行,我们在终点就会退出。在这儿,程序动态装载 Class 

对象,并把它加入 trashTypes (垃圾类型)列表,从而试图纠正这个问题。若仍然找不到真正有问题的地 

方,同时装载又是成功的,那么就重复调用factory 方法,重新试一遍。  

正如大家会看到的那样,这种设计方案最大的优点就是不需要改动代码。无论在什么情况下,它都能正常地 

使用(假定所有Trash 子类都包含了一个构建器,用以获取单个 double 参数)。  

  

1。 Trash 子类  

为了与原型机制相适应,对Trash 每个新子类唯一的要求就是在其中包含了一个构建器,指示它获取一个 

double 参数。Java 1。1 的“反射”机制可负责剩下的所有工作。  

下面是不同类型的Trash,每种类型都有它们自己的文件里,但都属于 Trash 包的一部分(同样地,为了方 

便在本章内重复使用):  

  

//: Aluminum。java   

// The Aluminum class with prototyping  

package c16。trash;  

  

public class Aluminum extends Trash {  

  private static double val = 1。67f;  



                                                                                   599 


…………………………………………………………Page 601……………………………………………………………

  public Aluminum(double wt) { super(wt); }  

  public double value() { return val; }  

  public static void value(double newVal) {  

    val = newVal;  

  }  

} ///:~  

//: Paper。java   

// The Paper class with prototyping  

package c16。trash;  

  

public class Paper extends Trash {  

  private static double val = 0。10f;  

  public Paper(double wt) { super(wt); }  

  public double value() { return val; }  

  public static void value(double newVal) {  

    val = newVal;  

  }  

} ///:~  

//: Glass。java   

// The Glass class with prototyping  

package c16。trash;  

  

public class Glass extends Trash {  

  private static double val = 0。23f;  

  public Glass(double wt) { super(wt); }  

  public double value() { return val; }  

  public static void value(double newVal) {  

    val = newVal;  

  }  

} ///:~  

  

下面是一种新的Trash 类型:  

  

//: Cardboard。java   

// The Cardboard class with prototyping  

package c16。trash;  

  

public class Cardboard extends Trash {  

  private static double val = 0。23f;  

  public Cardboard(double wt) { super(wt); }  

  public double value() { return val; }  

  public static void value(double newVal) {  

    val = newVal;  

  }  

} ///:~  

可以看出,除构建器以外,这些类根本没有什么特别的地方。  

  

2。 从外部文件中解析出Trash  

与Trash 对象有关的信息将从一个外部文件中读取。针对Trash 的每个方面,文件内列出了所有必要的信 

息——每行都代表一个方面,采用“垃圾(废品)名称:值”的固定格式。例如:  

  

c16。Trash。Glass:54  



                                                                                          600 


…………………………………………………………Page 602……………………………………………………………

c16。Trash。Paper:22  

c16。Trash。Paper:11  

c16。Trash。Glass:17  

c16。Trash。Aluminum:89  

c16。Trash。Paper:88  

c16。Trash。Aluminum:76  

c16。Trash。Cardboard:96  

c16。Trash。Aluminum:25  

c16。Trash。Aluminum:34  

c16。Trash。Glass:11  

c16。Trash。Glass:68  

c16。Trash。Glass:43  

c16。Trash。Aluminum:27  

c16。Trash。Cardboard:44  

c16。Trash。Aluminum:18  

c16。Trash。Paper:91  

c16。Trash。Glass:63  

c16。Trash。Glass:50  

c16。Trash。Glass:80  

c16。Trash。Aluminum:81  

c16。Trash。Cardboard:12  

c16。Trash。Glass:12  

c16。Trash。Glass:54  

c16。Trash。Aluminum:36  

c16。Trash。Aluminum:93  

c16。Trash。Glass:93  

c16。Trash。Paper:80  

c16。Trash。Glass:36  

c16。Trash。Glass:12  

c16。Trash。Glass:60  

c16。Trash。Paper:66  

c16。Trash。Aluminum:36  

c16。Trash。Cardboard:22  

注意在给定类名的时候,类路径必须包含在内,否则就找不到类。  

为解析它,每一行内容都会读入,并用字串方法 indexOf()来建立“:”的一个索引。首先用字串方法 

substring()取出垃圾的类型名称,接着用一个静态方法 Double。valueOf()取得相应的值,并转换成一个 

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