按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
new Beast(this; x; y; direction; speed;
new Color(r;g;b)));
}
return newBeasts;
}
public Vector beastListInSector(Beast viewer) {
Vector output = new Vector();
Enumeration e = beasts。elements();
Beast aBeast = (Beast)beasts。elementAt(0);
int counter = 0;
while(e。hasMoreElements()) {
aBeast = (Beast) e。nextElement();
if(aBeast != viewer) {
Point p = aBeast。position();
Point v = viewer。position();
float bearing =
aBeast。bearingFromPointAlongAxis(
v。x; v。y; viewer。currentDirection);
if(Math。abs(bearing) 《 fieldOfView / 2)
output。addElement(aBeast);
}
}
return output;
}
public void paint(Graphics g) {
Enumeration e = beasts。elements();
while(e。hasMoreElements()) {
((Beast)e。nextElement())。draw(g);
}
}
public static void main(String'' args) {
FieldOBeasts field = new FieldOBeasts();
field。xExtent = 640;
field。yExtent = 480;
Frame frame = new Frame(〃Field 'O Beasts〃);
// Optionally use a mand…line argument
// for the sleep time:
if(args。length 》= 1)
field。delay = Integer。parseInt(args'0');
frame。addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System。exit(0);
}
});
frame。add(field; BorderLayout。CENTER);
frame。setSize(640;480);
648
…………………………………………………………Page 650……………………………………………………………
field。init();
field。start();
frame。setVisible(true);
}
} ///:~
尽管这并非对Craig Reynold 的“Boids”例子中的行为完美重现,但它却展现出了自己独有的迷人之外。通
过对数字进行调整,即可进行全面的修改。至于与这种群聚行为有关的更多的情况,大家可以访问Craig
Reynold 的主页——在那个地方,甚至还提供了Boids 一个公开的 3D 展示版本:
http://hmt。/cwr/boids。html
为了将这个程序作为一个程序片运行,请在HTML 文件中设置下述程序片标志:
17。4 总结
通过本章的学习,大家知道运用Java 可做到一些较复杂的事情。通过这些例子亦可看出,尽管 Java 必定有
自己的局限,但受那些局限影响的主要是性能(比如写好文字处理程序后,会发现C++的版本要快得多——
这部分是由于 IO 库做得不完善造成的;而在你读到本书的时候,情况也许已发生了变化。但Java 的局限也
仅此而已,它在语言表达方面的能力是无以伦比的。利用 Java,几乎可以表达出我们想得到的任何事情。而
与此同时,Java 在表达的方便性和易读性上,也做足了功夫。所以在使用 Java 时,一般不会陷入其他语言
常见的那种复杂境地。使用那些语言时,会感觉它们象一个爱唠叨的老太婆,哪有Java 那样清纯、简练!而
且通过 Java 1。2 的JFC/Swing 库,AWT 的表达能力和易用性甚至又得到了进一步的增强。
17。5 练习
(1) (稍微有些难度)改写FieldOBeasts。java,使它的状态能够保持固定。加上一些按钮,允许用户保存
和恢复不同的状态文件,并从它们断掉的地方开始继续运行。请先参考第 10章的CADState。java ,再决定具
体怎样做。
(2) (大作业)以FieldOBeasts。java 作为起点,构造一个自动化交通仿真系统。
(3) (大作业)以ClassScanner。java 作为起点,构造一个特殊的工具,用它找出那些虽然定义但从未用过
的方法和字段。
(4) (大作业)利用JDBC,构造一个联络管理程序。让这个程序以一个平面文件数据库为基础,其中包含了
名字、地址、电话号码、E…mail 地址等联系资料。应该能向数据库里方便地加入新名字。键入要查找的名字
时,请采用在第15章的VLookup。java 里介绍过的那种名字自动填充技术。
649
…………………………………………………………Page 651……………………………………………………………
附录 A 使用非 JAVA 代码
JAVA 语言及其标准API (应用程序编程接口)应付应用程序的编写已绰绰有余。但在某些情况下,还是必须
使用非 JAVA 编码。例如,我们有时要访问操作系统的专用特性,与特殊的硬件设备打交道,重复使用现有的
非Java 接口,或者要使用“对时间敏感”的代码段,等等。与非 Java 代码的沟通要求获得编译器和“虚拟
机”的专门支持,并需附加的工具将Java 代码映射成非 Java 代码(也有一个简单方法:在第 15章的“一个
Web 应用”小节中,有个例子解释了如何利用标准输入输出同非Java 代码连接)。目前,不同的开发商为我
们提供了不同的方案:Java 1。1 有“Java 固有接口”(Java Native Interface,JNI),网景提出了自己的
“Java 运行期接口”(Java Runtime Interface)计划,而微软提供了J/Direct、“本源接口”(Raw
Native Interface,RNI)以及Java/ 集成方案。
各开发商在这个问题上所持的不同态度对程序员是非常不利的。若Java 应用必须调用固有方法,则程序员或
许要实现固有方法的不同版本——具体由应用程序运行的平台决定。程序员也许实际需要不同版本的Java 代
码,以及不同的Java 虚拟机。
另一个方案是CORBA (通用对象请求代理结构),这是由OMG (对象管理组,一家非赢利性的公司协会)开发
的一种集成技术。CORBA 并非任何语言的一部分,只是实现通用通信总线及服务的一种规范。利用它可在由
不同语言实现的对象之间实现“相互操作”的能力。这种通信总线的名字叫作ORB (对象请求代理),是由
其他开发商实现的一种产品,但并不属于 Java 语言规范的一部分。
本附录将对 JNI,J/DIRECT,RNI,JAVA/ 集成和 CORBA 进行概述。但不会作更深层次的探讨,甚至有时还
假定读者已对相关的概念和技术有了一定程度的认识。但到最后,大家应该能够自行比较不同的方法,并根
据自己要解决的问题挑选出最恰当的一种。
A。1 Java 固有接口
JNI 是一种包容极广的编程接口,允许我们从 Java 应用程序里调用固有方法。它是在 Java 1。1 里新增的,
维持着与Java 1。0 的相应特性—— “固有方法接口”(NMI)——某种程度的兼容。NMI 设计上一些特点使
其未获所有虚拟机的支持。考虑到这个原因,Java 语言将来的版本可能不再提供对NMI 的支持,这儿也不准
备讨论它。
目前,JNI 只能与用C 或C++写成的固有方法打交道。利用JNI,我们的固有方法可以:
■创建、检查及更新Java 对象(包括数组和字串)
■调用Java 方法
■俘获和丢弃“异常”
■装载类并获取类信息
■进行运行期类型检查
所以,原来在Java 中能对类及对象做的几乎所有事情在固有方法中同样可以做到。
A。1。1 调用固有方法
我们先从一个简单的例子开始:一个Java 程序调用固有方法,后者再调用Win32 的API 函数
MessageBox(),显示出一个图形化的文本框。这个例子稍后也会与J/Direct 一志使用。若您的平台不是
Win32,只需将包含了下述内容的C 头:
#include
替换成:
#include
并将对MessageBox()的调用换成调用 printf() 即可。
第一步是写出对固有方法及它的自变量进行声明的 Java 代码:
class ShowMsgBox {
public static void main(String '' args) {
ShowMsgBox app = new ShowMsgBox();
app。ShowMessage(〃Generated with JNI〃);
}
650
…………………………………………………………Page 652……………………………………………………………
private native void ShowMessage(String msg);
static {
System。loadLibrary(〃MsgImpl〃);
}
}
在固有方法声明的后面,跟随有一个 static 代码块,它会调用 System。loadLibrary() (可在任何时候调用
它,但这样做更恰当)System。loadLibrary()将一个 DLL 载入内存,并建立同它的链接。DLL 必须位于您的
系统路径,或者在包含了Java 类文件的目录中。根据具体的平台,JVM 会自动添加适当的文件扩展名。
1。 C 头文件生成器:javah
现在编译您的Java 源文件,并对编译出来的。class文件运行 javah。javah 是在 1。0版里提供的,但由于我
们要使用Java 1。1 JNI,所以必须指定…jni 参数:
javah …jni ShowMsgBox
javah 会读入类文件,并为每个固有方法声明在 C 或C++头文件里生成一个函数原型。下面是输出结果——
ShowMsgBox。h 源文件(为符合本书的要求,稍微进行了一下修改):
/* DO NOT EDIT THIS FILE
it is machine generated */
#include
/* Header for class ShowMsgBox */
#ifndef _Included_ShowMsgBox
#define _Included_ShowMsgBox
#ifdef __cplusplus
extern 〃C〃 {
#endif
/*
* Class: ShowMsgBox
* Method: ShowMessage
* Signature: (Ljava/lang/String;)