程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java的枚舉器(反復器)

java的枚舉器(反復器)

編輯:關於JAVA

在任何集合類中,必須通過某種方法在其中置入對象,再用另一種方法從中取得對象。畢竟,容納各種各樣的對象正是集合的首要任務。在Vector中,addElement()便是我們插入對象采用的方法,而elementAt()是提取對象的唯一方法。Vector非常靈活,我們可在任何時候選擇任何東西,並可使用不同的索引選擇多個元素。
若從更高的角度看這個問題,就會發現它的一個缺陷:需要事先知道集合的准確類型,否則無法使用。乍看來,這一點似乎沒什麼關系。但假若最開始決定使用Vector,後來在程序中又決定(考慮執行效率的原因)改變成一個List(屬於Java1.2集合庫的一部分),這時又該如何做呢?
可利用“反復器”(Iterator)的概念達到這個目的。它可以是一個對象,作用是遍歷一系列對象,並選擇那個序列中的每個對象,同時不讓客戶程序員知道或關注那個序列的基礎結構。此外,我們通常認為反復器是一種“輕量級”對象;也就是說,創建它只需付出極少的代價。但也正是由於這個原因,我們常發現反復器存在一些似乎很奇怪的限制。例如,有些反復器只能朝一個方向移動。
Java的Enumeration(枚舉,注釋②)便是具有這些限制的一個反復器的例子。除下面這些外,不可再用它做其他任何事情:
(1) 用一個名為elements()的方法要求集合為我們提供一個Enumeration。我們首次調用它的nextElement()時,這個Enumeration會返回序列中的第一個元素。
(2) 用nextElement()獲得下一個對象。
(3) 用hasMoreElements()檢查序列中是否還有更多的對象。

②:“反復器”這個詞在C++和OOP的其他地方是經常出現的,所以很難確定為什麼Java的開發者采用了這樣一個奇怪的名字。Java 1.2的集合庫修正了這個問題以及其他許多問題。

只可用Enumeration做這些事情,不能再有更多。它屬於反復器一種簡單的實現方式,但功能依然十分強大。為體會它的運作過程,讓我們復習一下本章早些時候提到的CatsAndDogs.java程序。在原始版本中,elementAt()方法用於選擇每一個元素,但在下述修訂版中,可看到使用了一個“枚舉”:
 

//: CatsAndDogs2.java
// Simple collection with Enumeration
import java.util.*;

class Cat2 {
  private int catNumber;
  Cat2(int i) {
    catNumber = i;
  }
  void print() {
    System.out.println("Cat number " +catNumber);
  }
}

class Dog2 {
  private int dogNumber;
  Dog2(int i) {
    dogNumber = i;
  }
  void print() {
    System.out.println("Dog number " +dogNumber);
  }
}

public class CatsAndDogs2 {
  public static void main(String[] args) {
    Vector cats = new Vector();
    for(int i = 0; i < 7; i++)
      cats.addElement(new Cat2(i));
    // Not a problem to add a dog to cats:
    cats.addElement(new Dog2(7));
    Enumeration e = cats.elements();
    while(e.hasMoreElements())
      ((Cat2)e.nextElement()).print();
    // Dog is detected only at run-time
  }
} ///:~


我們看到唯一的改變就是最後幾行。不再是:

for(int i = 0; i < cats.size(); i++)
((Cat)cats.elementAt(i)).print();

而是用一個Enumeration遍歷整個序列:

while(e.hasMoreElements())
((Cat2)e.nextElement()).print();

使用Enumeration,我們不必關心集合中的元素數量。所有工作均由hasMoreElements()和nextElement()自動照管了。
下面再看看另一個例子,讓我們創建一個常規用途的打印方法:
 

//: HamsterMaze.java
// Using an Enumeration
import java.util.*;

class Hamster {
  private int hamsterNumber;
  Hamster(int i) {
    hamsterNumber = i;
  }
  public String toString() {
    return "This is Hamster #" + hamsterNumber;
  }
}

class Printer {
  static void printAll(Enumeration e) {
    while(e.hasMoreElements())
      System.out.println(
        e.nextElement().toString());
  }
}

public class HamsterMaze {
  public static void main(String[] args) {
    Vector v = new Vector();
    for(int i = 0; i < 3; i++)
      v.addElement(new Hamster(i));
    Printer.printAll(v.elements());
  }
} ///:~


仔細研究一下打印方法:
 

static void printAll(Enumeration e) {
  while(e.hasMoreElements())
    System.out.println(
      e.nextElement().toString());
}

注意其中沒有與序列類型有關的信息。我們擁有的全部東西便是Enumeration。為了解有關序列的情況,一個Enumeration便足夠了:可取得下一個對象,亦可知道是否已抵達了末尾。取得一系列對象,然後在其中遍歷,從而執行一個特定的操作——這是一個頗有價值的編程概念,本書許多地方都會沿用這一思路。
這個看似特殊的例子甚至可以更為通用,因為它使用了常規的toString()方法(之所以稱為常規,是由於它屬於Object類的一部分)。下面是調用打印的另一個方法(盡管在效率上可能會差一些):
System.out.println("" + e.nextElement());
它采用了封裝到Java內部的“自動轉換成字串”技術。一旦編譯器碰到一個字串,後面跟隨一個“+”,就會希望後面又跟隨一個字串,並自動調用toString()。在Java 1.1中,第一個字串是不必要的;所有對象都會轉換成字串。亦可對此執行一次造型,獲得與調用toString()同樣的效果:
System.out.println((String)e.nextElement())
但我們想做的事情通常並不僅僅是調用Object方法,所以會再度面臨類型造型的問題。對於自己感興趣的類型,必須假定自己已獲得了一個Enumeration,然後將結果對象造型成為那種類型(若操作錯誤,會得到運行期違例)。

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