熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

applet 的參數化 -- 對數組進行初始化

2022-06-13   來源: Java核心技術 

  將列表數據提供給 applet
  看過關於 applet 參數化的上一篇技巧的讀者可能已經注意到我們的方法沒有對一類重要的對象進行初始化在本文中我們將研究如果利用類反射機制對一維數組和二位數組進行初始化我知道只有實現對更高維數組的處理才能使狂熱的科學家滿意但我將把那項工作作為練習留給您
  
  在我的上一篇技巧中只能處理基本類型的數組和字符串數組考慮到任何對象最終都能由基本數據類型和字符串構建而來所以這將不會構成多大的限制當然很容易將我們的技術加以擴展之後就能直接對其他類型的數據進行初始化
  
  數組是用來存儲列表數據的理想數據結構我們的技術使得向 applet 傳遞列表參數變得很簡單 通常利用動態生成 HTML 文檔的程序(如 servlet 或 CGI 腳本)將列表數據傳遞給 applet作為示例我們設想一個比賽記分板 appletHTML 生成器將會將當前的記分板數據庫輸出到 PARAM 標記中接著相應的數組將被完全初始化 這要歸功於我們的參數提取方法
  
  列表數據項的語法
  我們要實現的就是一個從 PARAM 標記中提取一維或是二維數組的方法一維數組的語法是
  
  PARAM NAME=myArray VALUE=element element elementN
  
  各元素之間的定界符是空格
  
  二位數組的語法是
  
  PARAM NAME=myMatrix VALUE=element element element |
  element element element |
  element element element
  
  各行之間的定界符是 | 符號這裡myMatrix 是一個 ( x ) 數組
  
  注意Java 支持不規則數組 不規則數組就是各行的長度不同的數組例如HTML 作者可能會按以下方式輸入帕斯卡三角形
  
  PARAM NAME=pascalTriangle VALUE= |
   |
   |
   |
   |
   |
  
  
  初始化完成之後pascalTriangle 域的內容將是
  
  pascalTriangle[] = {}
  pascalTriangle[] = { }
  pascalTriangle[] = { }
  pascalTriangle[] = { }
  pascalTriangle[] = { }
  pascalTriangle[] = { }
  pascalTriangle[] = { }
  
  通常程序員應該只聲明 pascalTriangle而不進行內存分配我們的提取方法負責分配內存但讓我們假定已為第四行分配了內存如下所示
  
  pascalTriangle[] = new int[];
  
  我們的方法將只提取前兩個元素這樣第四行的初始化結果將是
  
  pascalTriangle[] = { }
  
  數組知識回顧
  正如您在以上代碼清單中看到的那樣我們的方法實現有點深奧因此在研究源代碼之前回顧有關數組的幾點知識是個不錯的主意
  
  我們都對 Java 的類型層次結構比較熟悉Java 有一組預定義的基本數據類型(intfloat還有 Object 的子類的一個繼承樹Object 類是所有類的最終超類但 Java 中還存在一個不很出名的平行層次結構我稱其為數組層次結構您無論何時在類型層次結構中定義了一個新類型 Foo您實際上也同時定義了一個自動結合到數組層次結構中的新類型 Foo[]數組層次結構中的每個類(基本數據類型的數組除外)都是 Object[] 的子類容易引起混淆的是Object[] 和基本數據類型的數組都是 Object 的子類 表明了這一點
  

  
兩個平行的層次結構

  令人感到奇怪的是Java 根本就沒有多維數組只有一維數組多維數組實際上是一維數組的數組的數組的數組因此我們可以創建不規則數組事實上我們甚至可以不對某些行進行初始化而將它們保留為空值
  
  數組提取方法的實現
  現在我們可以查看源代碼了正如您所見其中加了大量注釋通常包含如此多的注釋不是個好習慣但在這裡我們要將已經抽象的 Java 數組包裝在由類反射機制提供的元數據抽象層中結果多數程序語句都不能表明其自身的含義所以在這種情況下對幾乎每個代碼行作注釋是無可非議的
  
  無論何時對一維或是二維數組進行初始化最終我們都需要用 HTML 作者輸入的行對一維數組進行初始化我們設計了一個方法來完成這一操作
  
  /**
  * 用符號處理器 (tokenizer) 的內容填充一維數組
  * 符號被轉換為數組的內容類型
  *
  * @param array 要填充的數組
  * @param elementTokens 包含要填入數組的符號的符號處理器
  */
  private static void fillOneDimensionalArray(Object array
  StringTokenizer elementTokens)
  throws IllegalAccessException {
  
  if (array != null && elementTokens != null && arraygetClass()isArray()) { // 雙重檢驗
  // 數組應該容納哪種類型的元素?
  Class componentType = arraygetClass()getComponentType();
  
  int numElements = untTokens();
  
  // 為數組元素賦值
  //
  // 請注意我們確保索引不會超出范圍可能未給數組分配組足夠的空間
  // 以致無法容納分析後的全部元素
  for (int j = ; j < ArraygetLength(array) && j < numElements; j++) {
  // 將符號轉換為數組所容納的類型
  // 然後將其添加到數組中
  if (componentTypeequals(booleanclass))
  ArraysetBoolean(array j BooleanvalueOf(elementTokensnextToken()trim())booleanValue());
  
  else if (componentTypeequals(byteclass))
  ArraysetByte(array j BytevalueOf(elementTokensnextToken()trim())byteValue());
  
  else if (componentTypeequals(charclass))
  ArraysetChar(array j elementTokensnextToken()charAt());
  
  else if (componentTypeequals(doubleclass))
  ArraysetDouble(array j DoublevalueOf(elementTokensnextToken()trim())doubleValue());
  
  else if (componentTypeequals(floatclass))
  ArraysetFloat(array j FloatvalueOf(elementTokensnextToken()trim())floatValue());
  
  else if (componentTypeequals(intclass))
  ArraysetInt(array j IntegervalueOf(elementTokensnextToken()trim())intValue());
  
  else if (componentTypeequals(longclass))
  ArraysetLong(array j LongvalueOf(elementTokensnextToken()trim())longValue());
  
  else if (componentTypeequals(shortclass))
  ArraysetShort(array j ShortvalueOf(elementTokensnextToken()trim())shortValue());
  
  else if (componentTypeequals(Stringclass))
  Arrayset(array j elementTokensnextToken());
  }
  }
  }
  
  我們使用 ClassgetComponentType() 方法獲取給定數組對象所容納的元素類型一旦我們獲得這些信息我們就知道應將行元素轉換為何種類型這是在一個循環語句中完成的
  
  您可能已猜到了ArraysetByte(Object obj int i byte datum) 用字節變量 datum 為 obj 數組的第 i 個元素賦值這相當於 ((byte[])obj)[i] = datum
  
  下面開始分析實現的核心部分我對 UtilinitializeApplet(Applet String) 方法(在Java 技巧 中實現)進行了擴展在其中添加了一個條件語句這個條件語句高速緩存數組域並對它們進行初始化
  
  import javaapplet*;
  import javalangreflect*;
  import javautil*;
  
  public abstract class Util {
  
  /**
  * 對 applet 的名稱以給定篩選前綴開頭的非 final 公共域進行初始化
  * 初始值將從 HTML PARAM 標記中讀取
  * *
  * @param applet 要初始化的 applet
  * @param filterPrefix 只對那些以此前綴開頭的域進行初始化
  *
  * 如果前綴為空值將對所有非 final 公共域進行初始化
  */
  public static void initializeApplet(Applet applet String filterPrefix) {
  
  Class metaclass = appletgetClass();
  Field[] fields = metaclassgetFields();
  String param = null;
  
  for (int i = ; i < fieldslength; i++) {
  try {
  param = appletgetParameter(fields[i]getName());
  
  if (param == null ||
  ModifierisFinal(fields[i]getModifiers()) ||
  ((filterPrefix != null) &&
  !fields[i]getName()startsWith(filterPrefix))
  )
  continue;
  
  Class fieldType = fields[i]getType();
  
  if (fieldTypeequals(booleanclass)) {
  fields[i]setBoolean(applet BooleanvalueOf(param)booleanValue());
  }
  else if (fieldTypeequals(byteclass)) {
  fields[i]setByte(applet BytevalueOf(param)byteValue());
  }
  
  /***************
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26052.html
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.