分享
 
 
 

applet的参数化--对数组进行初始化

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

将列表数据提供给 applet

看过关于 applet 参数化的上一篇技巧的读者可能已经注意到:我们的方法没有对一类重要的对象进行初始化。在本文中,我们将研究如果利用类反射机制对一维数组和二位数组进行初始化。我知道只有实现对更高维数组的处理才能使狂热的科学家满意,但我将把那项工作作为练习留给您。

在我的上一篇技巧中,只能处理基本类型的数组和字符串数组。考虑到任何对象最终都能由基本数据类型和字符串构建而来,所以这将不会构成多大的限制。当然,很容易将我们的技术加以扩展,之后就能直接对其他类型的数据进行初始化。

数组是用来存储列表数据的理想数据结构。我们的技术使得向 applet 传递列表参数变得很简单。 通常利用动态生成 HTML 文档的程序(如 servlet 或 CGI 脚本)将列表数据传递给 applet。作为示例,我们设想一个比赛记分板 applet。HTML 生成器将会将当前的记分板数据库输出到 PARAM 标记中,接着相应的数组将被完全初始化 -- 这要归功于我们的参数提取方法。

列表数据项的语法

我们要实现的就是一个从 PARAM 标记中提取一维或是二维数组的方法。一维数组的语法是:

PARAM NAME="myArray" VALUE="element1 element2 ... elementN"

各元素之间的定界符是空格。

二位数组的语法是:

PARAM NAME="myMatrix" VALUE="element11 element12 element13 |

element21 element22 element23 |

element31 element32 element33"

各行之间的定界符是 | 符号。这里,myMatrix 是一个 (3 x 3) 数组。

注意:Java 支持不规则数组。 不规则数组就是各行的长度不同的数组。例如,HTML 作者可能会按以下方式输入帕斯卡三角形:

PARAM NAME="pascalTriangle" VALUE=" 1 |

1 1 |

1 2 1 |

1 3 3 1 |

1 4 6 4 1 |

1 5 10 10 5 1 |

1 6 15 20 15 6 1"

初始化完成之后,pascalTriangle 域的内容将是:

pascalTriangle[0] = {1}

pascalTriangle[1] = {1, 1}

pascalTriangle[2] = {1, 2, 1}

pascalTriangle[3] = {1, 3, 3, 1}

pascalTriangle[4] = {1, 4, 6, 4, 1}

pascalTriangle[5] = {1, 5, 10, 10, 5, 1}

pascalTriangle[5] = {1, 6, 15, 20, 15, 6, 1}

通常,程序员应该只声明 pascalTriangle,而不进行内存分配。我们的提取方法负责分配内存。但让我们假定已为第四行分配了内存,如下所示:

pascalTriangle[3] = new int[2];

我们的方法将只提取前两个元素。这样,第四行的初始化结果将是:

pascalTriangle[3] = {1, 3}

数组知识回顾

正如您在以上代码清单中看到的那样,我们的方法实现有点“深奥”。因此,在研究源代码之前回顾有关数组的几点知识是个不错的主意。

我们都对 Java 的类型层次结构比较熟悉:Java 有一组预定义的基本数据类型(int、float...),还有 Object 的子类的一个继承树,Object 类是所有类的最终超类。但 Java 中还存在一个不很出名的平行层次结构,我称其为数组层次结构。您无论何时在类型层次结构中定义了一个新类型 Foo,您实际上也同时定义了一个自动结合到数组层次结构中的新类型 Foo[]。数组层次结构中的每个类(基本数据类型的数组除外)都是 Object[] 的子类。容易引起混淆的是:Object[] 和基本数据类型的数组都是 Object 的子类。图 1 表明了这一点。

图 1:两个平行的层次结构

令人感到奇怪的是,Java 根本就没有多维数组,只有一维数组。多维数组实际上是“一维数组的数组的数组的数组...”。因此,我们可以创建不规则数组。事实上,我们甚至可以不对某些行进行初始化,而将它们保留为空值。

数组提取方法的实现

现在我们可以查看源代码了。正如您所见,其中加了大量注释。通常,包含如此多的注释不是个好习惯,但在这里,我们要将已经抽象的 Java 数组包装在由类反射机制提供的元数据抽象层中。结果,多数程序语句都不能表明其自身的含义,所以在这种情况下对几乎每个代码行作注释是无可非议的。

无论何时对一维或是二维数组进行初始化,最终我们都需要用 HTML 作者输入的行对一维数组进行初始化。我们设计了一个方法来完成这一操作:

/**

* 用符号处理器 (tokenizer) 的内容填充一维数组。

* 符号被转换为数组的内容类型。

*

* @param array 要填充的数组。

* @param elementTokens 包含要填入数组的符号的符号处理器。

*/

private static void fillOneDimensionalArray(Object array,

StringTokenizer elementTokens)

throws IllegalAccessException {

if (array != null && elementTokens != null && array.getClass().isArray()) { // 双重检验。

// 数组应该容纳哪种类型的元素?

Class componentType = array.getClass().getComponentType();

int numElements = elementTokens.countTokens();

// 为数组元素赋值。

//

// 请注意,我们确保索引不会超出范围。可能未给数组分配组足够的空间,

// 以致无法容纳分析后的全部元素。

for (int j = 0; j < Array.getLength(array) && j < numElements; j++) {

// 将符号转换为数组所容纳的类型。

// 然后将其添加到数组中。

if (componentType.equals(boolean.class))

Array.setBoolean(array, j, Boolean.valueOf(elementTokens.nextToken().trim()).booleanValue());

else if (componentType.equals(byte.class))

Array.setByte(array, j, Byte.valueOf(elementTokens.nextToken().trim()).byteValue());

else if (componentType.equals(char.class))

Array.setChar(array, j, elementTokens.nextToken().charAt(0));

else if (componentType.equals(double.class))

Array.setDouble(array, j, Double.valueOf(elementTokens.nextToken().trim()).doubleValue());

else if (componentType.equals(float.class))

Array.setFloat(array, j, Float.valueOf(elementTokens.nextToken().trim()).floatValue());

else if (componentType.equals(int.class))

Array.setInt(array, j, Integer.valueOf(elementTokens.nextToken().trim()).intValue());

else if (componentType.equals(long.class))

Array.setLong(array, j, Long.valueOf(elementTokens.nextToken().trim()).longValue());

else if (componentType.equals(short.class))

Array.setShort(array, j, Short.valueOf(elementTokens.nextToken().trim()).shortValue());

else if (componentType.equals(String.class))

Array.set(array, j, elementTokens.nextToken());

}

}

}

我们使用 Class.getComponentType() 方法获取给定数组对象所容纳的元素类型。一旦我们获得这些信息,我们就知道应将行元素转换为何种类型。这是在一个循环语句中完成的。

您可能已猜到了,Array.setByte(Object obj, int i, byte datum) 用字节变量 datum 为 obj 数组的第 i 个元素赋值。这相当于 ((byte[])obj)[i] = datum。

下面开始分析实现的核心部分。我对 Util.initializeApplet(Applet, String) 方法(在“Java 技巧 57”中实现)进行了扩展,在其中添加了一个条件语句,这个条件语句高速缓存数组域并对它们进行初始化。

import java.applet.*;

import java.lang.reflect.*;

import java.util.*;

public abstract class Util {

/**

* 对 applet 的名称以给定筛选前缀开头的非 final 公共域进行初始化。

* 初始值将从 HTML PARAM 标记中读取。

* *

* @param applet 要初始化的 applet。

* @param filterPrefix 只对那些以此前缀开头的域进行初始化。

*

* 如果前缀为空值,将对所有非 final 公共域进行初始化。

*/

public static void initializeApplet(Applet applet, String filterPrefix) {

Class metaclass = applet.getClass();

Field[] fields = metaclass.getFields();

String param = null;

for (int i = 0; i < fields.length; i++) {

try {

param = applet.getParameter(fields[i].getName());

if (param == null ||

Modifier.isFinal(fields[i].getModifiers()) ||

((filterPrefix != null) &&

!fields[i].getName().startsWith(filterPrefix))

)

continue;

Class fieldType = fields[i].getType();

if (fieldType.equals(boolean.class)) {

fields[i].setBoolean(applet, Boolean.valueOf(param).booleanValue());

}

else if (fieldType.equals(byte.class)) {

fields[i].setByte(applet, Byte.valueOf(param).byteValue());

}

/***************

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有