程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 模擬垃圾回收站

模擬垃圾回收站

編輯:關於JAVA

這個問題的本質是若將垃圾丟進單個垃圾筒,事實上是未經分類的。但在以後,某些特殊的信息必須恢復,以便對垃圾正確地歸類。在最開始的解決方案中,RTTI扮演了關鍵的角色(詳見第11章)。
這並不是一種普通的設計,因為它增加了一個新的限制。正是這個限制使問題變得非常有趣——它更象我們在工作中碰到的那些非常麻煩的問題。這個額外的限制是:垃圾抵達垃圾回收站時,它們全都是混合在一起的。程序必須為那些垃圾的分類定出一個模型。這正是RTTI發揮作用的地方:我們有大量不知名的垃圾,程序將正確判斷出它們所屬的類型。

 

//: RecycleA.java 
// Recycling with RTTI
package c16.recyclea;
import java.util.*;
import java.io.*;

abstract class Trash {
  private double weight;
  Trash(double wt) { weight = wt; }
  abstract double value();
  double weight() { return weight; }
  // Sums the value of Trash in a bin:
  static void sumValue(Vector bin) {
    Enumeration e = bin.elements();
    double val = 0.0f;
    while(e.hasMoreElements()) {
      // One kind of RTTI:
      // A dynamically-checked cast
      Trash t = (Trash)e.nextElement();
      // Polymorphism in action:
      val += t.weight() * t.value();
      System.out.println(
        "weight of " +
        // Using RTTI to get type
        // information about the class:
        t.getClass().getName() +
        " = " + t.weight());
    }
    System.out.println("Total value = " + val);
  }
}

class Aluminum extends Trash {
  static double val  = 1.67f;
  Aluminum(double wt) { super(wt); }
  double value() { return val; }
  static void value(double newval) {
    val = newval;
  }
}

class Paper extends Trash {
  static double val = 0.10f;
  Paper(double wt) { super(wt); }
  double value() { return val; }
  static void value(double newval) {
    val = newval;
  }
}

class Glass extends Trash {
  static double val = 0.23f;
  Glass(double wt) { super(wt); }
  double value() { return val; }
  static void value(double newval) {
    val = newval;
  }
}

public class RecycleA {
  public static void main(String[] args) {
    Vector bin = new Vector();
    // Fill up the Trash bin:
    for(int i = 0; i < 30; i++)
      switch((int)(Math.random() * 3)) {
        case 0 :
          bin.addElement(new
            Aluminum(Math.random() * 100));
          break;
        case 1 :
          bin.addElement(new
            Paper(Math.random() * 100));
          break;
        case 2 :
          bin.addElement(new
            Glass(Math.random() * 100));
      }
    Vector 
      glassBin = new Vector(),
      paperBin = new Vector(),
      alBin = new Vector();
    Enumeration sorter = bin.elements();
    // Sort the Trash:
    while(sorter.hasMoreElements()) {
      Object t = sorter.nextElement();
      // RTTI to show class membership:
      if(t instanceof Aluminum)
        alBin.addElement(t);
      if(t instanceof Paper)
        paperBin.addElement(t);
      if(t instanceof Glass)
        glassBin.addElement(t);
    }
    Trash.sumValue(alBin);
    Trash.sumValue(paperBin);
    Trash.sumValue(glassBin);
    Trash.sumValue(bin);
  }
} ///:~


要注意的第一個地方是package語句:
package c16.recyclea;
這意味著在本書采用的源碼目錄中,這個文件會被置入從c16(代表第16章的程序)分支出來的recyclea子目錄中。第17章的解包工具會負責將其置入正確的子目錄。之所以要這樣做,是因為本章會多次改寫這個特定的例子;它的每個版本都會置入自己的“包”(package)內,避免類名的沖突。
其中創建了幾個Vector對象,用於容納Trash句柄。當然,Vector實際容納的是Object(對象),所以它們最終能夠容納任何東西。之所以要它們容納Trash(或者從Trash衍生出來的其他東西),唯一的理由是我們需要謹慎地避免放入除Trash以外的其他任何東西。如果真的把某些“錯誤”的東西置入Vector,那麼不會在編譯期得到出錯或警告提示——只能通過運行期的一個違例知道自己已經犯了錯誤。
Trash句柄加入後,它們會丟失自己的特定標識信息,只會成為簡單的Object句柄(上溯造型)。然而,由於存在多形性的因素,所以在我們通過Enumeration sorter調用動態綁定方法時,一旦結果Object已經造型回Trash,仍然會發生正確的行為。sumValue()也用一個Enumeration對Vector中的每個對象進行操作。
表面上持,先把Trash的類型上溯造型到一個集合容納基礎類型的句柄,再回過頭重新下溯造型,這似乎是一種非常愚蠢的做法。為什麼不只是一開始就將垃圾置入適當的容器裡呢?(事實上,這正是撥開“回收”一團迷霧的關鍵)。在這個程序中,我們很容易就可以換成這種做法,但在某些情況下,系統的結構及靈活性都能從下溯造型中得到極大的好處。
該程序已滿足了設計的初衷:它能夠正常工作!只要這是個一次性的方案,就會顯得非常出色。但是,真正有用的程序應該能夠在任何時候解決問題。所以必須問自己這樣一個問題:“如果情況發生了變化,它還能工作嗎?”舉個例子來說,厚紙板現在是一種非常有價值的可回收物品,那麼如何把它集成到系統中呢(特別是程序很大很復雜的時候)?由於前面在switch語句中的類型檢查編碼可能散布於整個程序,所以每次加入一種新類型時,都必須找到所有那些編碼。若不慎遺漏一個,編譯器除了指出存在一個錯誤之外,不能再提供任何有價值的幫助。
RTTI在這裡使用不當的關鍵是“每種類型都進行了測試”。如果由於類型的子集需要特殊的對待,所以只尋找那個子集,那麼情況就會變得好一些。但假如在一個switch語句中查找每一種類型,那麼很可能錯過一個重點,使最終的代碼很難維護。在下一節中,大家會學習如何逐步對這個程序進行改進,使其顯得越來越靈活。這是在程序設計中一種非常有意義的例子。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved