175
《Java 语言》实验指导书 萍编著 河南师范大学物理与信息工程学院

《Java语言》实验指导书read.pudn.com/downloads62/ebook/214971/%A1%B6Java%20%D3...7.Java多线程、图形与多媒体处理练习。 8.综合应用练习。 三、实验任务与时间安排

  • Upload
    others

  • View
    34

  • Download
    0

Embed Size (px)

Citation preview

《Java 语言》实验指导书

王萍编著

河南师范大学物理与信息工程学院

2

前言

一、 上机实验目的

上机实验的目的是提高学生的分析问题、解决问题的能力和动手能力,通过实践环节理解 Java

语言的基本结构和程序设计方法。通过亲手编程掌握 Java 语言编程的方法。

二、 实验基本内容

为了使学生在上机实验时目标明确,本实验指导书针对课程内容编写了 8 个实验。学生可以在课

内机时先完成指导书中给出的程序,理解所学的知识,在此基础上再编写其他应用程序。指导书中的

8 个实验如下。

1.Java 程序运行环境的下载、安装与配置。

2.Java 基本语法的编程练习。

3.面向对象编程练习。

4.Java 包、接口和异常处理的练习。

5.常用系统类的练习。

6.窗口与菜单界面编程练习。

7.Java 多线程、图形与多媒体处理练习。

8.综合应用练习。

三、实验任务与时间安排

《Java 语言》是一门实践性很强的课程,除了在课内安排的实验外,鼓励同学在课外用相关技术

进行编程练习。《Java 语言》上机实验时间为 20 学时,与教学内容同时进行上机实验。20 个上机学时

分为 7 个实验,在该单元学习后安排 1 次上机实验。

3

目录 实验 1 Java 运行环境的下载、安装、配置与运行 ....................................... 6

一、实验目的 .................................................................. 6

二、实验要求 .................................................................. 6

三、实验内容 .................................................................. 6

(一) SDK 的下载与安装。................................................. 6

(二) 设置环境变量 ...................................................... 9

(三) 安装 java 虚拟机 .................................................. 13

(四) 使用 EditPlus..................................................... 17

(五) 编译 Java 源程序 .................................................. 18

(六) 运行 Java 程序 .................................................... 18

(七) 使用 EditPlus 编译与运行程序 ...................................... 19

(八) 浏览 Applet 程序 .................................................. 23

实验 2 Java 基本语法练习 ......................................................... 24

一、实验目的 ................................................................. 24

二、实验要求 ................................................................. 24

三、实验内容 ................................................................. 24

(一) 声明不同数据类型的变量 ........................................... 24

(二) 了解变量的使用范围 ............................................... 25

(三) 使用关系运算符和逻辑运算符 ....................................... 26

(四) 使用数组 ......................................................... 27

(五) 使用表达式语句与复合语句 ......................................... 28

(六) 使用选择语句 ..................................................... 29

(七) 使用循环语句 ..................................................... 32

四、练习题 ................................................................... 35

实验 3 面向对象编程练习........................................................... 37

一、实验目的 ................................................................. 37

二、实验要求 ................................................................. 37

三、实验内容 ................................................................. 37

(一) 创建 Applet 应用小程序 ............................................ 37

(二) 创建对象与使用对象 ............................................... 39

(三) 显示当前日期和时间的程序 ......................................... 42

(四) 使用修饰符 ....................................................... 43

(五) 方法中的参数传递 ................................................. 46

4

(六) 类的继承性练习................................................... 48

(七) 类的多态性练习................................................... 53

四、思考题................................................................... 57

实验 4 包、接口与异常处理(exception) .......................................... 58

一、实验目的................................................................. 58

二、实验要求................................................................. 58

三、实验内容................................................................. 58

(一) 了解和使用 Java 的系统包.......................................... 58

(二) 创建并使用自定义包............................................... 60

(三) 使用接口的技术................................................... 62

(四) 创建自定义接口................................................... 65

(五) 异常处理机制..................................................... 66

(六) 异常对象的类型................................................... 67

(七) 使用 try…catch 语句处理异常...................................... 69

(八) 使用 throw 语句抛出异常........................................... 72

(九) throws 子句的使用 ................................................ 74

(十) 使用 finally 子句................................................. 75

(十一) 创建自定义异常类............................................... 77

四、思考题................................................................... 78

实验 5 常用系统类................................................................. 79

一、 实验目的............................................................. 79

二、 实验要求............................................................. 79

三、 实验内容............................................................. 79

(一) Applet 的生命周期 ................................................ 79

(二) 字符串与字符串类................................................. 82

(三) 输入输出流类..................................................... 84

(四) 数学函数类....................................................... 91

(五) 日期类........................................................... 92

(六) 向量类 Vector .................................................... 95

实验 6 图形用户界面 .............................................................. 97

一、 实验目的............................................................. 97

二、 实验要求............................................................. 97

三、 实验内容............................................................. 97

(一) 创建图形用户界面................................................. 97

(二) 事件处理机制.................................................... 100

(三)独立运行的窗口界面与匿名类........................................ 104

5

(四)使用 Swing 组件 .................................................... 109

(五)使用自定义对话框与内部类 .......................................... 113

四、 练习题 .............................................................. 117

实验 7 图形与多媒体处理 .......................................................... 118

一、 实验目的 ............................................................ 118

二、 实验要求 ............................................................ 118

三、 实验内容 ............................................................ 118

(一) 使用图形类 Graphics.............................................. 118

(二) 插入图像与播放音乐 .............................................. 122

(三) 多线程与动画 .................................................... 125

四、 练习题 .............................................................. 131

实验 8 综合练习.................................................................. 133

一、 实验目的 ............................................................ 133

二、 实验要求 ............................................................ 133

三、实验内容 ................................................................ 133

(一) 幻灯机效果——连续显示多幅图像 .................................. 133

(二) 使用滚动条改变背景颜色 .......................................... 134

(三) Applet 与 Application 合并运行的程序.............................. 136

(四) 对象的克隆 ...................................................... 138

(五) 正弦曲线 ........................................................ 140

(六) 四叶玫瑰线 ...................................................... 141

(七) 模拟网上购物结算 ................................................ 144

(八) 数字和图形时钟 .................................................. 147

(九) 在 Applet 的画布上随意画图 ....................................... 150

(十) 电闪雷鸣的动画 .................................................. 153

(十一) 文字的动画显示 ................................................ 157

(十二) 控制移动的文字 ................................................ 159

(十三) 水中倒影 ...................................................... 162

(十四) 到其它网站 .................................................... 164

(十五) 输入保存信息的窗口 ............................................ 166

(十六) 简单的文本编辑器 .............................................. 170

编程注意事项 ................................................................ 174

建议参考书 ...................................................................... 175

6

实验 1 Java 运行环境的下载、安装、配置与运行

一、实验目的

1. 掌握下载 Java SDK 软件包、EditPlus 编辑软件的方法。

2. 掌握设置 Java 程序运行环境的方法。

3. 掌握编写与运行 Java 程序的方法。

4. 了解 Java 语言的概貌。

5. 为学习 Java 语言和进行 Java 程序的实验做好准备工作。

二、实验要求

1. 下载、安装并设置 Java SDK 软件包。

2. 下载并安装 EditPlus 编辑软件。

3. 编写一个简单的 Java 程序。

4. 掌握运行 Java 程序的步骤。

5. 浏览 SDK 自带的 Applet 应用小程序。

三、实验内容

(一) SDK 的下载与安装

1.机器要求

Java 对机器运行要求不高。下面给出的是基于 Windows 平台的机器要求。

硬件要求:CPU PII 以上,64M 内存,1OOM 硬盘空间即可。

软件要求:Windows98/Me/XP/NT/2000,IE 5 以上。

2.下载 SDK

为了建立基于 SDK 的 Java 运行环境,需要先下载 Sun 的免费 SDK 软件包。SDK 包含了一整套

开发工具,其中包含对编程 有用的是 Java 编译器、Applet 查看器和 Java 解释器。

在浏览器中输入 http://java.sun.com/,可看到图 1.1 所示的 Sun 公司网站页面。

7

图 1.1

在页面右边“Popular Downloads”栏中可看到 新版的 SDK 软件包(早期版本称为 JDK),这

里显示的是“J2SE 1.4.2 SDK-NEW”(当前 新版)。单击“J2SE 1.4.2 SDK-NEW”超链接,可看到图

1.2 所示页面。

图 1.2

8

在页面的“Download J2SE v 1.4.2_01 ”栏可以选择下载 J2SE v 1.4.2_01 SDK 软件包。有两种选

择:一种是在线安装“Windows Installation”;一种是离线安装“Windows Offline Installation”。单击页

面中“SDK”列对应的“DOWNLOAD”超链接,可看到图 1.3 所示的下载协议说明书。

图 1.3

单击“ACCEPT”按钮,同意 Sun 公司的协议,可进入到图 1.4 所示的下载页面,单击“Download

j2sdk-1_4_2_01-windows-i586.exe”超链接,开始下载工作。

图 1.4

3.安装 SDK

运行下载的“j2sdk-1_4_2_01-windows-i586.exe”软件包,可安装 SDK,在安装过程中可以设置安

装路径及选择组件,系统默认的安装路径为 C:\ j2sdk1.4.2_01(这里选择 E 盘),默认的组件选择是全

部安装。

4.SDK 中的主要文件夹和文件

9

安装成功后,E:\ j2sdk1.4.2_01 中的文件和子目录结构如图 1.5 所示。

图 1.5

其中,bin 文件夹中包含编译器(javac.exe)、解释器(javac.exe)、Applet 查看器(appletviewer.exe)

等可执行文件,如图 1.6 所示。Demo 文件夹中包含一些源代码的程序示例。

图 1.6

(二) 设置环境变量

SDK 中的工具都是命令行工具,需要从命令行即 MS-DOS 提示符下运行它们。很多人可能会不

习惯,但这是 Sun 特意采取的策略,为的是把精力更多地投入到 Java 语言本身而不是花在开发工具上。

为了能正确方便的使用 SDK,可手工配置一些 Windows 的环境变量,Windows 98 与 Windows

/xp/NT/2000 的配置略有不同。

1.设置 Windows 98

在 C:\autoexec.bat 文件中,添加以下内容:

10

set path=%path%; E:\ j2sdk1.4.2_01\bin

set classpath=.; E:\ j2sdk1.4.2_01\lib\;%classpath%

E:\ j2sdk1.4.2_01\bin 为程序安装路径,如果安装时做了修改,这里必须做出相应的修改。“set path”

语句设置 Java 编译运行程序的路径,“set classpath”语句设置 Java 包的路径,其中的“.”表示在当前

目录下均可执行 Java 程序。autoexec.bat 文件修改后存盘,然后重新启动计算机,即完成了设置。

2.设置 Windows XP/NT/2000

以 Windows XP 为例说明设置过程。在桌面“我的电脑”图标上单击右键,选择“属性”菜单,

将出现系统特性设置界面,如图 1.7 所示。

图 1.7

在“高级”选项卡中单击“环境变量”按钮。将出现“环境变量”设置界面,如图 1.8 所示。

11

图 1.8

在“系统变量”框中选择“Path”,然后单击“编辑”按钮,在出现的“编辑系统变量”对话框中,

在“变量值”栏的命令前添加“E:\j2sdk1.4.2_01\bin;”命令,如图 1.9 所示。

图 1.9

用同样方法设置环境变量“classpath”,其值为“E:\j2sdk1.4.2_01\lib;”命令。

设置完成后,单击“开始”→“所有程序”→“附件”→“命令提示符”打开 DOS 窗口,在命

令提示符下输入“java”或“javac”,回车后,如果出现其用法参数提示信息,则安装正确,如图 1.10

所示。

12

图 1.10

3.设置 DOS 起始位置

为了在打开 DOS 窗口时可以直接进入包含你开发的 java 程序的路径下,下面以 Windows XP/2000

为例说明设置过程。

(1)首先建立一个存放 java 源程序的路径和文件夹,如将实验中建立的 java 源程序都存放在为

“e:\java\程序”文件夹中。

(2)单击“开始”→“所有程序”→“附件”→“命令提示符”,选择“命令提示符”选项右击,

在出现的下拉菜单中选择“属性”菜单,将打开“命令提示符 属性”对话框,如图 1.11 所示。

(3)在“命令提示符 属性”对话框中选择“快捷方式”选项,在“起始位置”栏输入“e:\java\

程序”,单击“确定”按钮。

进行了上面的设置后,打开 DOS 窗口时将直接进入“e:\java\程序>”路径下。

如果没有进行上述设置,可使用 DOS 命令,直接输入“e:”按回车进入到 e 盘,再输入“cd java”

到 e 盘的 java 子目录下,再输入“cd 程序”即可到“e:\java\程序>”路径下。

13

图 1.11

(三) 安装 java 虚拟机

为了在浏览器中正常浏览 java 程序,要在浏览器中安装 java 虚拟机,或需要打开浏览器禁止的

Java 功能。

1.下载并设置 Java(TM) 软件

Java (TM)软件中涉及 Web 交互的部分。它包括 Java 虚拟机和许多其它内容。有了它可以尽

情享受 Internet 提供的 佳内容,包括游戏、体育、聊天、电子邮件、艺术、财务工具等等。可到

http://java.sun.com/getjava/zh/downloLX3_1.html 下载免费的 Java(TM)软件。

下载完成后,打开 Windows 的“控制面板”窗口,如图 1.12 所示。

14

图 1.12

在“控制面板”窗口双击 图标,打开“Java(TM) Plug-in 控制面板”对话框,选择

“浏览器”选项,单击选取“Microsoft Internet Explorer”复选框。再单击“应用”按钮,如图

1.13 所示。

图 1.13

15

2.打开浏览器 Java 的功能

打开一个 IE 窗口,在浏览器菜单栏单击“工具”→“Internet 选项”命令,打开“Internet 选

项”对话框,选择“高级”选项卡,选取“Java(sun)”下的单选框;选取“Microsoft VM”下的第

一个选项“启用 Java JIT 编译器”,如图 1.14 所示。

图 1.14

选择“安全”选项卡,如图 1.15 所示,单击“自定义级别...”按钮,将打开“安全设置”对话

框,如图 1.16 所示。

16

图 1.15

图 1.16

17

在“安全设置”对话框中把“Microsoft VM”中的 java 权限设置为“安全等级-中”;把“脚本”

中的“java 小程序脚本”设置为“启用”和“活动脚本”设置为“启用”。

完成上面操作后,关闭浏览器再重新打开即可在浏览器中正常浏览 java 小程序。

(四) 使用 EditPlus

要编写 Java 程序,需要有文本编辑器。可以使用操作系统提供的 Edit 或记事本作为编辑器, 好

选择 EditPlus 编辑软件,它可以使用不同颜色显示 Java 的关键字和类名,简单好用,同时可以对程序

进行编译和运行。

1.下载并安装 EditPlus 编辑软件

EditPlus 编辑软件的安装方法很简单,安装软件提示要求去做即可。

2.编写在屏幕上显示文字“欢迎你学习 Java 语言!”的文件(Hello.java)。打开 EditPlus 编辑软

件,如图 1.17 所示,在其右边文本区输入如下代码。

public class Hello {

public static void main(String args[]) {

System.out.println("欢迎你学习 Java 语言!");

}

}

图 1.17

3.将文件命名为 Hello.java,保存为文本文件格式文件,注意保存文件的路径。根据前面环境变量

的设置,Hello.java 应该保存在“e:\java\程序>”的路径下。

18

(五) 编译 Java 源程序

Java 源程序编写后,要使用 Java 编译器(javac.exe)进行编译,将 Java 源程序编译成可执行

的程序代码。Java 源程序都是扩展名为 .java 的文本文件。编译时首先读入 Java 源程序,然后进行

语法检查,如果出现问题就终止编译。语法检查通过后,生成可执行程序代码即字节码,字节码文件

名和源文件名相同,扩展名为 .class。

1. 打开命令提示符窗口(MS-DOS 窗口)进入 Java 源程序所在路径。

2. 键入编译器文件名和要谝译的源程序文件名,如图 1.18 所示。

javac Hello.java,

3. 按回车键开始编译(注意:文件名 H 要大写,否则运行会出问题)。

如果源程序没有错误,则屏幕上没有输出,键入 “dir”按回车键后可在目录中看到生成了一个

同名字的.class 文件“Hello. class” ,如图 1.18 所示。否则,将显示出错信息。

图 1.18

(六) 运行 Java 程序

使用 Java 解释器(java.exe)可将编译后的字节码文件 Hello.class 解释为本地计算机代码。

在命令提示符窗口或 MS-DOS 窗口键入解释器文件名和要解释的字节码文件名 java Hello,按回

车键即开始解释并可看到运行结果,如果看到如图 1.19 所示结果,表明程序运行成功了,这是一种字

符方式的应用程序其结果显示在屏幕。

19

图 1.21

(七) 使用 EditPlus 编译与运行程序

1.打开 EditPlus 编辑软件,单击“工具”→“配置用户工具”菜单,如图 1.22 所示。

图 1.22

2.在打开的“参数设置”窗口如图 1.23、图 1.24 所示配置编译与运行环境。

(1)设置“编译”工具

单击“组名称”按钮确定工具组的名称。单击“添加工具”按钮,从弹出的快捷菜单中选择“程

序文件”命令。在“菜单文字”栏中输入“编译”文字;在“命令”栏中输入或通过文件夹选择 javac.exe

文件的路径;在“参数”栏选择“文件名称”;在“初始目录”栏输入 Java 程序所在的路径。

(2)设置“运行”工具,同样的方法可以设置“运行”工具。请同学自己练习。

20

图 1.23

图 1.24

21

3.编译与运行

设置工具后,在“工具”菜单下的下拉菜单中就可以对 Java 程序进行编译与运行操作了。

(1)单击“工具”→“编译”菜单,如图 1.25 所示。就开始对选中的程序进行编译处理。该过

程要等一会儿。

图 1.25

(2)编译通过后,可在右下方窗口看到编译结果,如图 1.26 所示。如果程序有问题,会看到提示。

图 1.26

22

(3)编译成功后,可运行该程序。单击“工具”→“运行”菜单,如图 1.27 所示。

图 1.27

(4)运行成功后,可在右下方窗口看到程序的运行结果,如图 1.28 所示。

图 1.28

23

(八) 浏览 Applet 程序

在下载的\j2sdk1.4.2_01\demo\applets\Clock 文件夹中用浏览器打开网页文件 example1.html,

就可以看到一个嵌入到 Web 页面的 Applet 开始运行,一个模拟时钟出现在网页上,如图 1.29 所示,

显示出系统当前时间。

图 1.29

24

实验 2 Java 基本语法练习

一、实验目的

1. 了解 Java 的数据类型

2. 掌握各种变量的声明方式。

3. 理解运算符的优先级。

4. 掌握 Java 基本数据类型、运算符与表达式、数组的使用方法。

5. 理解 Java 程序语法结构,掌握顺序结构、选择结构和循环结构语法的程序设计方法。

6. 通过以上内容,掌握 Java 语言的编程规则。

二、实验要求

1. 编写一个声明 Java 不同数据类型变量的程序。

2. 编写一个使用运算符、表达式、变量的程序。

3. 编写一个使用 Java 数组的的程序。

4. 编写表达式语句、复合语句的程序。

5. 编写使用不同选择结构的程序。

6. 编写使用不同循环结构结构的程序。

三、实验内容

(一) 声明不同数据类型的变量

1.编写声明不同数据类型变量的程序文件 LX2_1.java,源代码如下。

public class LX2_1 {

public static void main(String args[]) {

byte b=0x55;

short s=0x55ff;

int i=1000000;

long l=0xffffL;

char c='a';

float f=0.23F;

double d=0.7E-3;

25

boolean B=true;

String S="这是字符串类数据类型";

System.out.println("字节型变量 b = "+b);

System.out.println("短整型变量 s = "+s);

System.out.println(" 整型变量 i = "+i);

System.out.println("长整型变量 l = "+l);

System.out.println("字符型变量 c = "+c);

System.out.println("浮点型变量 f = "+f);

System.out.println("双精度变量 d = "+d);

System.out.println("布尔型变量 B = "+B);

System.out.println("字符串类对象 S = "+S);

}

}

2.编译并运行该程序,结果如图 2.1 所示。

图 2.1

(二) 了解变量的使用范围

1.建立 LX2_2.java 文件,通过本程序了解变量的使用范围,源代码如下。

public class LX2_2 {

static int i=10;

public static void main(String args[]) {

{

int k=10;

System.out.println("i="+i);

System.out.println("k="+k);

}

26

System.out.println("i="+i);

System.out.println("k="+k);

//编译时将出错,已出 k 的使用范围

}

}

2.编译 LX2_2.java

此时会出现错误提示如图 2.2 所示。因为变量 k 在方法块中声明,在方法块之外它是不存在的,

所以编译时会出错。

图 2.2

3.修改上面的程序。

4.成功运行该程序。

思考:LX2_2.java 程序说明了什么问题?

(三) 使用关系运算符和逻辑运算符

1.建立使用关系运算符和逻辑运算符的程序文件,源代码如下。

class LX2_3 {

public static void main(String args[]) {

int a=25, b=20, e=3, f=0;

boolean d=a<b;

System.out.println("a=25,b=20,e=3,f=0");

System.out.println("因为关系表达式 a<b 为假,所以其逻辑值为 : "+d);

if (e!=0 && a/e>5)

System.out.println("因为 e 非 0 且 a/e 为 8 大于 5,所以输出 a/e= "+a/e);

if (f!=0 && a/f>5)

System.out.println("a/f = "+a/f);

else

27

System.out.println("因为 f 值为 0,所以输出 f = "+f);

}

}

2.编译并运行该程序,结果如图 2.3 所示。

图 2.3

(四) 使用数组

1.建立使用数组的程序,本程序建立了一个长度为 5 的 1维数组,一个长度为 12 的 2 维数组,

源代码如下。

public class LX2_4 {

public static void main(String args[]) {

int a[]=new int[5];

int arr1[][]=new int[3][4];

a[0]=10;

a[1]=10+a[0];

a[2]=30;

a[3]=40;

a[4]= a[1]+ a[2];

arr1[0][0]=0; arr1[0][1]=1; arr1[0][2]=2;

arr1[1][0]=3; arr1[1][1]=4; arr1[1][2]=5;

arr1[2][0]=6; arr1[2][1]=7; arr1[2][2]=8;

System.out.println("a["+0+"] = "+a[0]);

System.out.println("a["+1+"] = "+a[1]);

System.out.println("a["+2+"] = "+a[2]);

System.out.println("a["+3+"] = "+a[3]);

System.out.println("a["+4+"] = "+a[4]);

System.out.println("arr1("+0+","+0+") = "+arr1[0][0]);

28

System.out.println("arr1("+0+","+1+") = "+arr1[0][1]);

System.out.println("arr1("+0+","+2+") = "+arr1[0][2]);

System.out.println("arr1("+1+","+0+") = "+arr1[1][0]);

System.out.println("arr1("+1+","+1+") = "+arr1[1][1]);

System.out.println("arr1("+1+","+2+") = "+arr1[1][2]);

}

}

2.编译并运行程序,结果如图 2.4 所示。

图 2.4

(五) 使用表达式语句与复合语句

1. 建立包含表达式语句程序,源代码如下。

class LX2_5{

public static void main(String[] args) {

int k, i=3, j=4;

k=20*8/4+i+j*i;

System.out.println("表达式(20*8/4+i+j*i)="+k);

}

}

2. 建立包含复合语句程序,源代码如下。

class LX2_6{

public static void main(String args[]) {

int k, i=3, j=4;

k=i+j;

System.out.println("在复合块外的输出 k="+k);

29

{

float f;

f=j+4.5F;

i++;

System.out.println("在复合块内的输出 f="+f);

System.out.println("在复合块内的输出 k="+k);

}

System.out.println("在复合块外的输出 i="+i);

}

}

3. 编译并运行上述两个源程序,结果如图 2.5、2.6 所示。

图 2.5 图 2.6

4. 将变量 i 在块内定义会怎样?改变其他变量的位置看看会发生什么变化。

思考:指出程序的复合结构以及变量的使用范围。

(六) 使用选择语句

1.使用 if...else 语句

(1)程序功能:使用 if...else 语句构造多分支,判断某一年是否为闰年。闰年的条件是符合下

面二者之一:能被 4 整除,但不能被 100 整除;能被 4 整除,又能被 100 整除。

(2)编写源程序文件,代码如下。

public class LX2_7 {

public static void main(String args[]) {

boolean leap;

int year=2005;

if ((year%4==0 && year%100!=0) || (year%400==0)) // 方法 1

System.out.println(year+" 年是闰年");

else

30

System.out.println(year+" 年不是闰年");

year=2008; // 方法 2

if (year%4!=0)

leap=false;

else if (year%100!=0)

leap=true;

else if (year%400!=0)

leap=false;

else

leap=true;

if (leap==true)

System.out.println(year+" 年是闰年");

else

System.out.println(year+" 年不是闰年");

year=2050; // 方法 3

if (year%4==0) {

if (year%100==0) {

if (year%400==0)

leap=true;

else

leap=false;

}

else

leap=false;

}

else

leap=false;

if (leap==true)

System.out.println(year+" 年是闰年");

else

System.out.println(year+" 年不是闰年");

}

}

31

(3)编译运行程序,其结果如图 2.7 所示。

图 2.7

思考:本程序中有几个选择语句,哪些具有嵌套关系?

2.使用 switch 语句

(1)程序功能:在不同温度时显示不同的解释说明。

(2)程序源代码如下。

class LX2_8{

public static void main(String args[]) {

int c=38;

switch (c<10?1:c<25?2:c<35?3:4) {

case 1:

System.out.println(" "+c+"℃ 有点冷。要多穿衣服。");

case 2:

System.out.println(" "+c+"℃ 正合适。出去玩吧。");

case 3:

System.out.println(" "+c+"℃ 有点热。");

default:

System.out.println(" "+c+"℃ 太热了!开空调。");

}

}

}

(3)编译运行程序,其结果如图 2.8 所示。

图 2.8

32

(七) 使用循环语句

1. for 循环语句练习

(1) 程序功能:按 5 度的增量打印出一个从摄氏温度到华氏温度的转换表。

(2) 程序源代码如下。

class LX2_9{

public static void main (String args[]) {

int h,c;

System.out.println("摄氏温度 华氏温度");

for (c=0; c<=40; c+=5) {

h=c*9/5+32;

System.out.println(" "+c+" "+h);

}

}

}

(3)编译并运行程序,其结果如图 2.9 所示。

图 2.9

2. while 循环语句练习

(1)程序功能:运行程序后从键盘输入数字 1/2/3 后,可显示抽奖得到的奖品;如果输入其它数

字或字符显示“没有奖品给你!”。

(2)程序源代码如下。

import java.io.*;

class LX2_10 {

public static void main(String args[]) throws IOException {

char ch;

33

System.out.println("按 1/2/3 数字键可得大奖!");

System.out.println("按空格键后回车可退出循环操作.");

while ((ch=(char)System.in.read())!=' ') {

System.in.skip(2); // 跳过回车键

switch (ch) {

case '1':

System.out.println("恭喜你得大奖,一辆汽车!");

break;

case '2':

System.out.println("不错呀,你得到一台笔记本电脑!");

break;

case '3':

System.out.println("没有白来,你得到一台冰箱!");

break;

default:

System.out.println("真不幸,你没有奖品!下次再来吧。");

}

}

}

}

(3)编译源程序。

(4)在命令提示符窗口运行程序,然后分别按 1、2、3、r 结果如图 2.10 所示。

图 2.10

34

3.do…while 循环语句练习

(1) 程序功能:求 1+2+…+100 之和,并将求和表达式与所求的和显示出来。

(2) 程序源代码如下。

class LX2_11 {

public static void main(String args[]) {

int n=1, sum=0;

do {

sum+=n++;

}

while (n<=100);

System.out.println("1+2+...+100 ="+sum);

}

}

(3)编译并运行程序,结果如图 2.11 所示。

图 2.11

4.多重循环练习

(1)输出九九乘法表的程序,源代码如下。

public class LX2_12

{

public static void main(String args[])

{

int i,j,n=9;

System.out.print(" * |");

for (i=1;i<=n;i++)

System.out.print(" "+i);

System.out.print("\n-------|");

for (i=1;i<=n;i++)

System.out.print("----");

System.out.println();

35

for (i=1;i<=n;i++)

{

System.out.print(" "+i+" |");

for (j=1;j<=i;j++)

System.out.print(" "+i*j);

System.out.println();

}

}

}

(2)编译并运行程序,结果如图 2.12 所示。

图 2.12

四、练习题

1.分析下面的程序,说出下面的程序为什么是死循环?

class Sum {

public static void main(String args[]) {

int i=1,n=10,s=0;

while (i<=n)

s = s + i;

System.out.println("s="+s);

}

}

2.分析下面源程序的结构,写出运行结果。

class CircleArea {

final static double PI=3.14159;

public static void main(String args[]) {

36

double r1=8.0, r2=5.0;

System.out.println("半径为"+r1+"的圆面积="+area(r1));

System.out.println("半径为"+r2+"的圆面积="+area(r2));

}

static double area(double r) {

return (PI*r*r);

}

}

2.编写程序,根据考试成绩的等级打印出百分制分数段。设 A 为 90 分以上、B 为 80 分以上、C

为 70 分以上、D 为 60 分以上、E 为 59 分以下。要求在程序中使用开关语句。

3.完整下面的程序,利用 break 语句和带标号的 break 语句分别退出一重循环和二重循环。

for (i=0; i<10; i++)

{

int j=i*10

while(j<100)

{

if (j==10)

break;

j=j+5;

}

}

37

实验 3 面向对象编程练习

一、实验目的

通过编程和上机实验理解 Java 语言是如何体现面向对象编程基本思想,了解类的封装方法,以及

如何创建类和对象,了解成员变量和成员方法的特性,掌握 OOP 方式进行程序设计的方法,了解类的

继承性和多态性的作用。

二、实验要求

1. 编写一个体现面向对象思想的程序。

2. 编写一个创建对象和使用对象的方法的程序。

3. 编写一个显示当前日期和时间的程序。

4. 编写不同成员变量修饰方法的程序。

5. 编写不同成员方法修饰方法的程序。

6. 编写体现类的继承性(成员变量、成员方法、成员变量隐藏)的程序。

7. 编写体现类的多态性(成员方法重载、构造方法重载)的程序。

三、实验内容

(一) 创建 Applet 应用小程序

1.创建一个 Applet 应用程序 LX3_1.java 文件。

(1)程序功能:建立一个 Applet 小程序,使其可以进行简单的加法运算。该程序要包含类、接

口、属性、方法、事件等面向对象的基本元素。

(2)程序源代码如下。

import java.awt.*;

import java.awt.event.*;

import java.applet.Applet;

public class LX3_1 extends Applet implements ActionListener {

Label label1=new Label("+");

Label label2=new Label("=");

38

TextField field1=new TextField(6);

TextField field2=new TextField(6);

TextField field3=new TextField(6);

Button button1=new Button("相加");

public void init() { // 初始化

add(field1);

add(label1);

add(field2);

add(label2);

add(field3);

add(button1);

button1.addActionListener(this);

}

public void actionPerformed(ActionEvent e) { // 处理按钮事件

int x=Integer.parseInt(field1.getText())+Integer.parseInt(field2.getText());

field3.setText(Integer.toString(x)); // 数值转换为字符串

}

}

2.编写一个浏览 Applet 应用程序的页面文件 LX3_1.HTML,源代码如。

<html>

<applet code="LX3_1.class" height=200 width=400>

</applet>

</html>

3. 将 LX3_1.java 源程序编译为 LX3_1.class 文件

4. 使用浏览器或使用小程序查看器浏览 LX3_1.HTML 文件(即在命令提示符窗口输入:

appletviewer LX3_1.HTML),运行结果如图 3.1 所示。

39

图 3.1

思考:

1.如何创建 applet 小程序?需要注意哪些问题?

2.本程序包含面向对象的哪些基本元素?

(二) 创建对象并使用对象

1.编写 Applet 程序

(1)程序功能:这个 Applet 程序要在页面上输出两个矩形,并伴有文字输出。

(2)LX3_2.java 程序的源代码如下。

import java.awt.*;

import java.applet.Applet;

public class LX3_2 extends Applet {

MyBox b1=new MyBox();//创建对象 b1

MyBox b2=new MyBox(170,20,60,60); //创建对象 b2

public void paint(Graphics g) {

b1.setPosition(20,20);

b1.setSize(60,60);

b1.draw(g);

g.drawString("矩形 1 的 X 位置: "+b1.getX(), 20, 100);

g.drawString("矩形 1 的 Y 位置: "+b1.getY(), 20, 120);

40

b2.draw(g);

g.drawString("矩形 2 的 X 位置: "+b2.getX(), b2.getX(), b2.getY()+80);

g.drawString("矩形 2 的 Y 位置: "+b2.getY(), b2.getX(), b2.getY()+100);

}

}

class MyBox {

private int x, y, width, height;

MyBox() {

x=0;

y=0;

width=0;

height=0;

}

MyBox(int xPos, int yPos, int w, int h) {

x=xPos;

y=yPos;

width=w;

height=h;

}

public void setPosition (int xPos, int yPos) {

x=xPos;

y=yPos;

}

public void setSize (int w, int h) {

width=w;

height=h;

}

public int getX() {

return x;

41

}

public int getY() {

return y;

}

public void draw(Graphics g) {

g.drawRect(x, y, width, height);

}

}

2.编写一个浏览 Applet 应用程序的页面文件 LX3_2.HTML

<html>

<applet code=" LX3_2.class" height=200 width=400>

</applet>

</html>

3. 将 LX3_2.java 源程序编译为 LX3_2.class 文件

4. 使用浏览器或使用小程序查看器浏览LX3_2.HTML文件(即在命令提示符下输入:appletviewer

LX3_2.HTML),运行结果如图 3.2 所示。

图 3.2

思考:程序的结构。类与对象的关系。对象创建、使用、销毁的过程。

42

(三) 编写显示当前日期和时间的程序

1.编写 Applet 类文件 LX3_3.java

(1)程序功能:该程序通过使用一个自定义类 Time,实现显示当前日期和时间的功能,程序运

行结果应与图 3.3 类似。

图 3.3

(2)LX3_3.java 程序源代码如下。

import java.awt.Graphics;

import java.applet.Applet;

import java.util.Calendar;

class Time {

private Calendar t;

private int y, m, d, hh, mm, ss;

Time (){

t=Calendar.getInstance();

y=t.get(t.YEAR);

m=t.get(t.MONTH)+1;

d=t.get(t.DATE);

hh=t.get(t.HOUR_OF_DAY);

mm=t.get(t.MINUTE);

ss=t.get(t.SECOND);

43

}

public String getDate() {

return y+" 年"+m+"月"+d+"日";

}

public String getTime() {

String s=hh+" 时"+mm+"分"+ss+"秒";

return s;

}

}

public class LX3_3 extends Applet {

Time t=new Time();

public void paint(Graphics g) {

g.drawString("当前日期:"+t.getDate(),50,40);

g.drawString("当前时间:"+t.getTime(),50,80);

}

}

2.编写浏览 LX3_3 类的页面文件 LX3_3.html

<html>

<applet codebase=e:/java/程序 code=LX3_3.class width=300 height=120>

</applet >

</html>

3.在浏览器中浏览程序运行结果。

注意:本程序中传递了一个 Graphics 类的对象 g,并调用了 g 的方法 drawString。

(四) 使用修饰符

有时需要公开一些变量和方法,有时需要禁止其他对象使用变量和方法,这时可以使用修饰符来

实现这个目的。

常用的修饰符如下。

[public] [private] [protected] [package] [static] [final] [transient] [volatile]

44

不同修饰符的访问控制权限如表 3.1 所示。

表 3.1

修饰符 类 子类 包 所有类和包

public √ √ √ √

private √

protected √ √* √

package √ √

1.程序功能:通过两个类 StaticDemo、LX3_4 说明静态变量/方法与实例变量/方法的区别。

2.编写类文件 LX3_4.java,程序源代码如下。

class StaticDemo {

static int x;

int y;

public static int getX() {

return x;

}

public static void setX(int newX) {

x = newX;

}

public int getY() {

return y;

}

public void setY(int newY) {

y = newY;

}

}

public class LX3_4 {

public static void main(String[] args) {

System.out.println("静态变量 x="+StaticDemo.getX());

System.out.println("实例变量 y="+StaticDemo.getY()); // 非法,编译时将出错

StaticDemo a= new StaticDemo();

StaticDemo b= new StaticDemo();

45

a.setX(1);

a.setY(2);

b.setX(3);

b.setY(4);

System.out.println("静态变量 a.x="+a.getX());

System.out.println("实例变量 a.y="+a.getY());

System.out.println("静态变量 b.x="+b.getX());

System.out.println("实例变量 b.y="+b.getY());

}

}

3.对上面的源程序进行编译,会出现如图 3.4 所示的出错提示。

图 3.4

4.将源程序中的出错语句删除或使用解释符//隐藏起来,例如,

//System.out.println("实例变量 y="+StaticDemo.getY());

5.重新编译并运行该程序,结果如图 3.5 所示。

图 3.5

static 声明的成员变量/方法被视为类的成员变量/方法,而不把它当作实例对象的成员变量/方

法。换句话说,静态变量/方法是类固有的,可以直接引用,其它成员变量/方法仅仅被声明,生成实

例对象后才存在,才可以被引用。基于这样的事实,也把静态变量/方法称为类变量/方法,非静态变

量称为实例变量/方法。

46

从实验结果可以得出以下几点结论:

·类的静态变量可以直接引用,而非静态变量则不行。类的静态变量相当于某些程序语言的全局

变量。

·静态方法只能使用静态变量,不能使用实例变量。因为对象实例化之前,实例变量不可用。

·类的静态变量只有一个版本,所有实例对象引用的都是同一个版本。

·对象实例化后,每个实例变量都被制作了一个副本,它们之间互不影响。

(五) 方法中参数传递的练习

在其它语言中,函数调用或过程调用时参数有传值调用和传地址调用之分。在 Java 中,方法中的

参数传递可以分为传值调用或对象方法调用等方式。传值调用即传递的参数是基本数据类型,调用方

法时在方法中将不能改变参数的值,这意味着只能使用它们。对象调用是指先调用对象,再调用对象

的方法,这种方式可以修改允许存取的成员变量。所以,如果不想改变参数的值,可以采用传值调用

的方法。如果想改变参数的值,可采用对象调用的方法,间接修改参数的值。

1.编写一个传值调用的程序文件 LX3_5.java。

(1)程序功能:程序首先给整型变量 x 和 y 赋一个初值 10,然后使用传值调用方式调用方法 ff1

对 x 和 y 做乘方及输出 x 和 y 的乘方值, 后再输出 x 和 y 的乘方值。

(2)程序源代码如下。

class LX3_5 {

public static void main(String[] args) {

int x=10, y=10;

ff1(x, y);

System.out.println("x="+x+", y="+y);

}

static void ff1(int passX, int passY) {

passX=passX*passX;

passY=passY*passY;

System.out.println("passX="+passX+", passY="+passY);

}

}

(3)编译 LX3_5.java,其运行结果如图 3.6 所示。

47

图 3.6

(4)分析其运行结果

这个程序没有实现预期的结果,原因是 ff1 方法采用了传值调用。调用 ff1 方法时,将产生两个

参数 passX 和 passY,x 和 y 的值被传递给这两个参数。尽管在方法中计算了参数的平方,但从 ff1

方法返回后,参数消失,此时 x 和 y 的值仍是初值。

2.编写一个调用对象方法的程序文件 LX3_6.java。

(1)程序功能:通过调用对象的方法在方法调用后修改了成员变量的值。

(2)LX3_6.java 程序源代码如下。

class LX3_6 {

public static void main(String[] args) {

Power p=new Power();

p.ff2(10,10);

System.out.println("方法调用后 x="+p.x+", y="+p.y);

}

}

class Power{

int x=10, y=10;

void ff2(int passX, int passY) {

System.out.println("初始时 x="+x+", y="+y);

x=passX*passX;

y=passY*passY;

System.out.println("方法调用中 x="+x+", y="+y);

}

}

(3)编译 LX3_6.java,其运行结果如图 3.7 所示。

48

图 3.7

以上两个实验例子仅仅是为了说明 Java 编程中参数传递时要注意的问题,在实际编程中是不可取

的,因为完全可以采用其它更好的方法来实现参数的传递。例如,前面还使用过传递对象的方式。

思考:方法的参数传递有哪些方式?区别时什么?

(六) 类的继承性练习

1. 进一步理解继承的含义

新类可从现有的类中产生,并保留现有类的成员变量和方法并可根据需要对它们加以修改。新类

还可添加新的变量和方法。这种现象就称为类的继承。

当建立一个新类时,不必写出全部成员变量和成员方法。只要简单地声明这个类是从一个已定义

的类继承下来的,就可以引用被继承类的全部成员。被继承的类称为父类或超类(superclass),这个

新类称为子类。

Java 提供了一个庞大的类库让开发人员继承和使用。设计这些类是出于公用的目的,因此,很少

有某个类恰恰满足你的需要。你必须设计自己的能处理实际问题的类,如果你设计的这个类仅仅实现

了继承,则和父类毫无两样。所以,通常要对子类进行扩展,即添加新的属性和方法。这使得子类要

比父类大,但更具特殊性,代表着一组更具体的对象。继承的意义就在于此。

2. 创建公共类 LX3_7_P

(1)编写程序文件 LX3_7_P.java,源代码如下。

public class LX3_7_P

{

protected String xm; //具有保护修饰符的成员变量

protected int xh;

void setdata(String m,int h) //设置数据的方法

{

xm =m;

xh = h;

}

public void print() //输出数据的方法

{

49

System.out.println(xm+", "+xh);

}

}

(2)编译 LX3_7_P.java,产生类文件 LX3_7_P.class。

3.创建继承的类

(1)程序功能:通过 LX3_7_P 类产生子类 LX3_8,其不仅具有父类的成员变量 xm(姓名)、xh(学

号),还定义了新成员变量 xy(学院)、xi(系)。在程序中调用了父类的 print 方法,同时可以看出

子类也具有该方法。

(2)编写 LX3_8.java 程序,源代码如下。

class LX3_8 extends LX3_7_P

{

protected String xy;

protected String xi;

public static void main(String args[])

{

LX3_7_P p1 = new LX3_7_P();

p1.setdata("帅零",12321) ;

p1.print();

LX3_8 s1 = new LX3_8() ;

s1.setdata("郭丽娜",12345); //调用父类的成员方法

s1.xy="经济管理学院"; //访问本类的成员变量

s1.xi="信息管理系"; //访问本类的成员变量

s1.print();

System.out.print(s1.xm+", "+s1.xy+", "+s1.xi);

}

}

(3)编译并运行程序,其结果如图 3.8 所示。

图 3.8

注意:公共类 LX3_7_P 与 LX3_8 类要在同一文件夹(路径)内。

50

3.了解成员变量的隐藏方式

所谓隐藏是指子类重新定义了父类中的同名变量,在子类 Line 中重新定义了 x 为 x1,y 为 y1,

隐藏了父类 Point 中的两个成员变量 x 和 y。子类执行自己的方法时,操作的是子类的变量,子类执

行父类的方法时,操作的是父类的变量。在子类中要特别注意成员变量的命名,防止无意中隐藏了父

类的关键成员变量,这有可能给程序带来麻烦。

4.了解成员方法的覆盖方式

(1)方法覆盖的定义与作用

通过继承子类可以继承父类中所有可以被子类访问的成员方法,但如果子类的方法与父类方法同

名,则不能继承,此时称子类的方法覆盖了父类的方法,简称为方法覆盖(override)。方法覆盖为子

类提供了修改父类成员方法的能力。例如,子类可以修改层层继承下来的 Object 根类的 toString 方

法,让它输出一些更有用的信息。下面的程序显示了在子类 Circle 中添加 toString 方法,用来返回

圆半径和圆面积信息。

(2)编写覆盖 Object 类 toString 方法的程序文件 LX3_9.java,源代码如下。

class Circle {

private int radius;

Circle(int r) {

setRadius(r);

}

public void setRadius(int r) {

radius=r;

}

public int getRadius() {

return radius;

}

public double area() {

return 3.14159*radius*radius;

}

public String toString() {

return "圆半径:"+getRadius()+" 圆面积:"+area();

}

}

public class LX3_9{

public static void main(String args[]) {

Circle c=new Circle(10);

51

System.out.println("\n"+c.toString());

}

}

(3)编译并运行程序,其结果如图 3.9 所示。

图 3.9

(4)程序结构分析。

程序添加了 toString 方法并修改了它的返回值。由于 toString 和继承下来的 Object 类的方法名

相同、返回值类型相同,因此覆盖了超类 Object 中的 toString 方法。

方法覆盖时要特别注意:

用来覆盖的子类方法应和被覆盖的父类方法保持同名、相同的返回值类型,以及相同的参数个数

和参数类型。

5.This、super 和 super()的使用

(1)程序功能:说明 this、super 和 super()的用法。程序首先定义 Point(点)类,然后创建

点的子类 Line(线)。 后通过 LX3_10 类输出线段的长度。

程序中通过 super(a,b)调用父类 Point 的构造方法为父类的 x和 y 赋值。在子类 Line 的 setLine

方法中,因为参数名和成员变量名相同,为给成员变量赋值,使用 this 引用,告诉编译器是为当前类

的成员变量赋值。在 length 和 toString 方法中使用父类成员变量时,使用 super 引用,告诉编译器

使用的是父类的成员变量。

(2)使用 this、 super 和 super()的程序文件 LX3_10.java,源代码如下。

class Point {

protected int x, y;

Point(int a, int b) {

setPoint(a, b);

}

public void setPoint(int a, int b) {

x=a;

y=b;

}

}

52

class Line extends Point {

protected int x, y;

Line(int a, int b) {

super(a, b);

setLine(a, b);

}

public void setLine(int x, int y) {

this.x=x+x;

this.y=y+y;

}

public double length() {

int x1=super.x, y1=super.y, x2=this.x, y2=this.y;

return Math.sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));

}

public String toString() {

return "直线端点:[" + super.x + "," + super.y + "] [" +

x + "," + y + "] 直线长度:" + this.length();

}

}

public class LX3_10{

public static void main(String args[]) {

Line line=new Line(50, 50);

System.out.println("\n"+line.toString());

}

}

(3)编译并运行程序,结果如图 3.10 所示。

图 3.10

53

(七) 类的多态性练习

1. 理解类的多态性

类的继承发生在多个类之间,而类的多态只发生在同一个类上。在一个类中,可以定义多个同名

的方法,只要确定它们的参数个数和类型不同。这种现象称为类的多态。

多态使程序简洁,为程序员带来很大便利。在 OOP 中,当程序要实现多个相近的功能时,就给相

应的方法起一个共同的名字,用不同的参数代表不同的功能。这样,在使用方法时不论传递什么参数,

只要能被程序识别就可以得到确定的结果。

类的多态性体现在方法的重载(overload)上,包括成员方法和构造方法的重载。

2. 方法的重载

方法的重载是指对同名方法的不同使用方式。

(1)程序功能:对不同的数进行排序输出。在 IntSort 类中定义 3 个同名的方法 sort,在

(2)编写 LX3_11.java 文件,源代码如下。

import java.awt.Graphics;

import java.applet.Applet;

class IntSort {

public String sort(int a, int b) {

if (a>b)

return a+" "+b;

else

return b+" "+a;

}

public String sort(int a, int b, int c) {

int swap;

if (a<b) {

swap=a;

a=b;

b=swap;

}

if (a<c) {

swap=a;

a=c;

c=swap;

}

54

if (b<c) {

swap=b;

b=c;

c=swap;

}

return a+" "+b+" "+c;

}

public String sort(int arr[]) {

String s=" ";

int swap;

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

for (int j=0; j<arr.length-1; j++)

if (arr[j]>arr[j+1]) {

swap=arr[j];

arr[j]=arr[j+1];

arr[j+1]=swap;

}

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

s=s+arr[i]+" ";

return s;

}

}

public class LX3_11 extends Applet {

IntSort s=new IntSort();

public void paint(Graphics g) {

int a=30, b=12, c=40;

int arr[]={34,8,12,67,44,98,52,23,16,16};

g.drawString("两个数的排序结果:"+s.sort(a,b),30,30);

g.drawString("三个数的排序结果:"+s.sort(a,b,c),30,60);

g.drawString("数组的排序结果:"+s.sort(arr),30,90);

}

}

55

(3)编译并运行程序,结果如图 3.11 所示。

图 3.11

(4)三个同名方法

public String sort (int a, int b)

public String sort (int a, int b, int c)

public String sort (int arr[])

(5)编写 LX3_11 类文件的页面文件 LX3_11.html

<html>

<applet codebase=e:/java/程序 code=LX3_11.class width=420 height=380>

</applet >

</html>

3.构造方法的重载

构造方法的名称和类同名,没有返回类型。尽管构造方法看起来和一般的成员方法没有差别,但

它不是方法,也不是类的成员。因此,构造方法不能直接调用,只能由 new 操作符调用。

构造方法对于类是十分重要的,对象的初始化任务要靠构造方法来完成。

重载构造方法的目的是提供多种初始化对象的能力,使程序员可以根据实际需要选用合适的构造

方法来初始化对象。

(1) 编写构造方法 RunDemo 的重载程序文件 LX3_12,源代码如下。

class RunDemo {

private String userName, password;

56

RunDemo() {

System.out.println("全部为空!");

}

RunDemo(String name) {

userName=name;

}

RunDemo(String name, String pwd) {

this(name);

password=pwd;

check();

}

void check() {

String s=null;

if (userName!=null)

s="用户名:"+userName;

else

s="用户名不能为空!";

if (password!="12345678")

s=s+" 口令无效!";

else

s=s+" 口令:********";

System.out.println(s);

}

}

public class LX3_12 {

public static void main(String[] args) {

new RunDemo();

new RunDemo("刘新宇");

new RunDemo(null,"邵丽萍");

new RunDemo("张驰","12345678");

}

}

57

(2)编译并运行程序,结果如图 3.12 所示。

图 3.12

(3)三个构造方法,其中

第一个无参构造方法RunDemo() 的实际作用是对成员变量赋缺省初值,由于userName和password

都是 String 类,所以它们的缺省初值为 null。

第二个构造方法 RunDemo(String) 只有一个参数,用来对成员变量 userName 赋初值。

第三个构造方法 RunDemo(String, String) 有两个参数,并有更多的内容,首先调用 this(name),

其实际作用就是调用当前类的构造方法 RunDemo(String name);然后对成员变量 password 赋值;

后调用 check 方法来检查 userName 和 password,类似于一般程序的口令验证。

重载构造方法的执行由对象根据实际参数的个数、类型和顺序确定。

四、思考题

1. 说明使用变量之前是不是都要先声明变量。说明使用变量之前是不是都要先赋值,为什

么。

2. 说明什么是构造方法。

3. 说明程序中有多个类时如何确定源程序文件的名称。

4. 说明类的继承和多态有什么作用,在使用上应该注意什么问题。

58

实验 4 包、接口与异常处理(exception)

一、实验目的

了解 Java 中包(package)、接口(interface)和异常处理(exception)的作用,掌握包、接口、

异常处理的设计方法。

二、实验要求

1. 了解 Java 系统包的结构。

2. 掌握创建自定义包的方法。

3. 掌握使用系统接口的技术和创建自定义接口的方法。

4. 理解系统异常处理的机制和创建自定义异常的方法。

三、实验内容

(一) 了解并使用 Java 的系统包

1. API 包、接口、异常处理的作用

包是类和接口的集合。利用包可以把常用的类或功能相似的类放在一个包中。Java 语言提供系统

包,其中包含了大量的类,可以在编写 Java 程序时直接引用它们。为便于管理和使用它们,将这些类

分为了不同的包。包又称类库或 API 包,所谓 API(Application Program Interface)即应用程序接

口。API 包—方面提供丰富的类与方法供大家使用,如画图形、播放声音等,另一方面又负责和系统

软硬件打交道,圆满实现用户程序的功能。所有 Java API 包都以“java.”开头,以区别用户创建的

包。

接口解决了 Java 不支持多重继承的问题,可以通过实现多个接口达到与多重继承相同的功能。

处理程序运行时的错误和设计程序同样重要,只有能够完善处理运行时出错的程序,软件系统才

能长期稳定地运行,异常处理就是说明如何处理程序运行时出错的问题。

2.上网浏览 Java API 文档

在地址 http://java.sun.com/j2se/1.4.2/docs/api/index.html 上,可以看到 Java 系统提供的

Java API 文档,类文档的内容主要是:类层次、类及用途描述、成员变量列表、构造方法列表、成员

方法列表、从类层次上继承的方法列表、成员变量的详细说明、构造方法详细说明、成员方法详细说

59

明。在这里可以看到 Java 提供的 Java API 文档的 新内容。如图 4.1 所示。

图 4.1

在右上方选择 Class 标题,并在左下角框中移动滑块,选择 object 类,可以看到 object 类的所

有方法和构造方法。如图 4.2 所示。

60

图 4.2

3.了解 Applet 类的方法。

(二) 创建并使用自定义包

1.自定义包的声明方式

<package> <自定义包名>

声明包语句必须添加在源程序的第一行,表示该程序文件声明的全部类都属于这个包。

2.创建自定义包 Mypackage

在存放源程序的文件夹中建立一个子文件夹 Mypackage。例如,在“E:\java\程序”文件夹之中

创建一个与包同名的子文件夹 Mypackage(E:\java\程序\Mypackage),并将编译过的 class 文件放入

该文件夹中。注意:包名与文件夹名大小写要一致。再添加环境变量 classpath 的路径,例如:

E:\j2sdk1.4.2_01\lib; E:\java\程序

3.在包中创建类

(1)YMD.java 程序功能:在源程序中,首先声明使用的包名 Mypackage,然后创建 YMD 类,该类

具有计算今年的年份,可以输出一个带有年月日的字符串的功能。

(2)编写 YMD.java 文件,源代码如下。

package Mypackage; //声明存放类的包

import java.util.*; //引用 java.util 包

public class LX4_1_YMD {

private int year,month,day;

public static void main(String[] arg3){}

public LX4_1_YMD(int y,int m,int d) {

year = y;

month = (((m>=1) & (m<=12)) ? m : 1);

day = (((d>=1) & (d<=31)) ? d : 1);

}

public LX4_1_YMD() {

this(0,0,0);

}

61

public static int thisyear() {

return Calendar.getInstance().get(Calendar.YEAR);//返回当年的年份

}

public int year() {

return year;//返回年份

}

public String toString(){

return year+"-"+month+"-"+day;//返回转化为字符串的年-月-日

}

}

(3)编译 LX4_1_YMD.java 文件,然后将 LX4_1_YMD.class 文件存放到 Mypackage 文件夹中。

3.编写使用包 Mypackage 中 LX4_1_YMD 类的程序

(1)LX4_2.java 程序功能:给定某人姓名与出生日期,计算该人年龄,并输出该人姓名,年龄,

出生日期。程序使用了 LX4_1_YMD 的方法来计算年龄。

(2)编写 LX4_2.java 程序文件,源代码如下。

import Mypackage.LX4_1_YMD; //引用 Mypackage 包中的 LX4_1_YMD 类

public class LX4_2

{

private String name;

private LX4_1_YMD birth;

public static void main(String args[])

{

LX4_2 a = new LX4_2("张驰",1990,1,11);

a.output();

}

public LX4_2(String n1,LX4_1_YMD d1)

{

name = n1;

birth = d1;

}

public LX4_2(String n1,int y,int m,int d)

{

this(n1,new LX4_1_YMD(y,m,d));//初始化变量与对象

62

}

public int age() //计算年龄

{

return LX4_1_YMD.thisyear() - birth.year(); //返回当前年与出生年的差即年龄

}

public void output()

{

System.out.println("姓名 : "+name);

System.out.println("出生日期: "+birth.toString());

System.out.println("今年年龄 : "+age());

}

}

(3)编译并运行程序,结果如图 4.3 所示。

图 4.3

(三) 使用接口技术

1.接口的定义与作用

接口可以看作是没有实现的方法和常量的集合。接口与抽象类相似,接口中的方法只是做了声明,

而没有定义任何具体的操作方法。使用接口是为了解决 Java 语言中不支持多重继承的问题。单继承可

使语言本身结构简单,层次清楚,易于管理,安全可靠,避免冲突。但同时限制了语言的功能。为了

在实际应用中实现多重继承的功能,Java 使用了接口技术,一个类可以实现多个接口以达到使用公用

常量和一些常用的方法。

2.实现 MouseListener 和 MouseMotionListener 两个接口

(1)编写实现接口的程序文件 LX4_3.java,源代码如下。

import java.applet.Applet;

import java.awt.*;

import java.awt.event.*;

63

public class LX4_3 extends Applet implements MouseListener, MouseMotionListener {

int x1, y1, x2, y2;

public void init() {

addMouseListener(this);

addMouseMotionListener(this);

}

public void paint(Graphics g) {

g.drawLine (x1, y1, x2, y2);

}

public void mousePressed(MouseEvent e) { // 记录起点坐标

x1=e.getX();

y1=e.getY();

}

public void mouseClicked(MouseEvent e) {}

public void mouseEntered(MouseEvent e) {}

public void mouseExited(MouseEvent e) {}

public void mouseReleased(MouseEvent e) {}

public void mouseDragged(MouseEvent e) { // 记录终点坐标

x2=e.getX();

y2=e.getY();

repaint();

}

public void mouseMoved(MouseEvent e) {}

}

(2)程序分析:

从 LX4_3 类的声明语句中

public class DrawL extends Applet implements MouseListener, MouseMotionListener

可以看到使用 implements 关键字实现了 MouseListener 和 MouseMotionListener 两个接口。

在 LX4_3 类中还实现了 MouseListener 接口中定义的 5 个方法:

1)public void mousePressed(MouseEvent e) { // 记录起点坐标

x1=e.getX();

64

y1=e.getY(); }

2)public void mouseClicked(MouseEvent e) {}

3)public void mouseEntered(MouseEvent e) {}

4)public void mouseExited(MouseEvent e) {}

5)public void mouseReleased(MouseEvent e) {}

其中只是具体实现了 mousePressed 方法。其它都为空方法。

还实现了 MouseMotionListener 接口的两个方法:

1)public void mouseDragged(MouseEvent e) { // 记录终点坐标

x2=e.getX();

y2=e.getY();

repaint(); }

2) public void mouseMoved(MouseEvent e) {}

注意:在实现接口时,要实现所有接口中定义的所有方法,方法的实现可以具有具体的实现内容,

也可以是抽象的方法,即只有方法名或参数,没有变量、没有具体操作语句,只有一对大括号{}的空

方法。

(3)编译 LX4_3.java 文件。

(4)编写 LX4_3.html 文件,源代码如下。

<html>

<applet codebase=e:/java/程序 code=LX4_3.class width=320 height=180>

</applet >

</html>

(5)在浏览器中打开 LX4_3.html 文件,在窗口中拖动鼠标可以随意画出一条线如图 4.4 所示。

65

图 4.4

(四) 创建自定义接口

1.创建自定义接口的语法格式

如同使用包一样,程序员也可创建自定义接口。创建自定义接口要使用声明接口语句,格式如下:

[修饰符] <interface> <自定义接口名> {

… // 静态常量及方法声明

}

2.创建自定义接口程序文件 LX4_4_JK.java。

(1)程序功能:在程序中声明一个自定义接口 Nl,用来计算一个人年龄。

(2)编写 N1.java 程序文件,源代码如下。

interface LX4_4_JK{ //定义接口

int year = 2004;

int age();

void output();

}

说明:在 LX4_4_JK 接口中声明了两个方法:age()和 output () 以及一个整型常量 year。

注意:接口名首字母要大写。

3.编译 LX4_4_JK.java 程序文件,生成 LX4_4_JK.class 文件。以后其它类即可使用 LX4_4_JK

接口了。

4.编写使用接口 LX4_4_JK 的程序文件 LX4_5.java,源代码如下。

public class LX4_5 implements LX4_4_JK{ //实现接口

String xm; //类自己的成员变量(姓名)

int csrq; //类自己的成员变量(出生日期)

public LX4_5(String n1,int y){ //类构造方法

xm = n1;

csrq = y;

}

public int age(){ //实现接口的方法

66

return year - csrq; //这里直接使用了接口中的常量 year

}

public void output() { //实现接口的方法

System.out.println(this.xm +"今年的年龄是"+ this.age()+"岁");

}

public static void main (String args[]) //类自己的成员方法

{

LX4_5 a = new LX4_5("张驰",1990);

a.output();

}

}

5.编译并运行程序,结果如图 4.5 所示。

图 4.5

(五) 了解异常处理机制

1. 错误与异常

在程序执行期间,会有许多意外的事件发生。例如,程序申请内存时没有申请到、对象还未创建

就被使用、死循环等,称为运行错误。根据错误的性质将运行错误分为错误与异常两种类型。

(1)错误

程序进入了死循环或内存溢出,这类现象称为错误或致命性错误。错误只能在编程阶段解决,运

行时程序本身无法解决,只能依靠其它程序干预,否则会一直处于一种不正常的状态。

(2)异常

运算时除数为 0,或操作数超出数据范围,打开一个文件时发现文件不存在,网络连接中断等等,

这类运行错误现象称为异常。对于异常情况,可在源程序中加入异常处理代码,当程序出现异常时,

由异常处理代码调整程序运行流程,使程序仍可正常运行直到正常结束。

由于异常是可以检测和处理的,所以产生了相应的异常处理机制。而错误处理一般由系统承担。

对于一个应用软件,异常处理机制是不可缺少的。程序员必须在程序中考虑每一个可能发生的异

常情况并进行处理,以保证程序在任何情况下都能正常运行。事实证明,一个仔细设计了异常处理的

程序,可以长时间的可靠运行,而不容易发生致命的错误,如程序被迫关闭、甚至系统终止等等。所

以学会进行异常情况处理对于想编写功能完善且具有实用价值的程序员来说是必不可少的。

67

2. 异常发生的原因

(1)Java 虚拟机检测到了非正常的执行状态,这些状态可能是由以下几种情况引起的:

·表达式的计算违反了 Java 语言的语义,例如整数被 0 除。

·在载入或链接 Java 程序时出错。

·超出了某些资源限制,例如使用了太多的内存。

(2)Java 程序代码中的 throw 语句被执行。

(3)异步异常发生。异步异常的原因可能有:

·Thread 的 stop 方法被调用。

·Java 虚拟机内部错误发生。

3.异常处理机制

发生异常后,怎么处理异常呢?

Java 提供了异常处理机制来处理异常。分为两个步骤:

(1)抛出异常

Java 是这样规定的:当语义限制被违反时,将会抛出(throw)异常,即产生一个异常事件,生

成一个异常对象,并把它提交给运行系统,再由运行系统寻找相应的代码来处理异常。一个异常对象

可以由 Java 虚拟机来产生,也可以由运行的方法生成。异常对象中包含了异常事件类型、程序运行状

态等必要信息。

(2)捕获异常

异常抛出后,运行时系统从生成异常对象的代码开始,沿方法的调用栈进行查找,直到找到包含

相应处理的方法代码,并把异常对象交给该方法为止,这个过程称为捕获(catch)异常。

简单说异常处理机制就是:当语义限制被违反时,将会抛出异常对象,并将引起程序流程从异常

发生点转移到程序员指定的处理异常方法代码处进行异常处理。

(六) 了解异常对象的类型

在异常发生后,系统会产生一个异常事件,生成一个异常对象,有哪些异常对象呢?这些异常对

象来自哪些类呢?

Java 中的异常类具有层次结构组织。其中,Throwable 类是 Error 错误类和 Exception 异常类的

父类,它是 Object 的直接子类。RuntimeException 运行时异常类是 Exception 异常类的子类。如图

4.6 所示。

68

图 4.6

1.Exception 异常类的子类

(1)RuntimeException 运行时异常类

RuntimeException 类主要包括以下异常子类:

·ArithmeticException 算术异常类:表示遇到了异常的算术问题,例如被 0 整除。

·ArrayStoreException 数组下标越界异常类:试图把与数组类型不相符的值存人数组。

·ClassCastException 类型强制转换异常类:试图把一个对象的引用强制转换为不合适的类型。

·IndexOutOfBoundsException 下标越界异常类:下标越界。

·NullPointerException 空指针异常类:试图使用一个空的对象引用。

·SecurityException 违背安全原则异常类:检测到了违反安全的行为。

(2)NoSuchMethodException 方法未找到异常

(3)java.awt.AWTException 图形界面异常类

(4)java.io.TOException 输入输出异常类

java.io.TOException 类的子类有:

·IOException:申请 I/O 操作没有正常完成。

·EOFException:在输入操作正常结束前遇到了文件结束符。

·FileNotFoundException:在文件系统中,没有找到由文件名字符串指定的文件。

(5)Exception 异常类的其它子类

·EmptyStackException:试图访问一个空堆栈中的元素。

·NoSuchFieldException:试图访问一个不存在的域。

·NoSuchMethodException:试图访问不存在的方法。

·ClassNotFoundException:具有指定名字的类或接口没有被发现。

·CloneNotSupportedException:克隆一个没有实现 Cloneable 接口的类。

·IllegalAccessException:试图用给出了完整的路径信息的字符串加载一个类,但是当前正在

执行的方法无法访问指定类,因为该类不是 public 类型或在另一个包中。

69

·InstantiationException:试图使用 Class 的 newInstance 方法创建一个对象实例,但指定的

对象没有被实例化,因为它是一个接口、抽象类或者一个数组。

·InterruptedException:当前的线程正在等待,而另一个线程使用了 Thread 的 interrupt 方法

中断了当前线程。

2.Error 错误类的子类

(1)VirtualMachineError 虚拟机错误

OutOfMemoryError 内存溢出错误

StackOverflowError 栈溢出错误

(2) LinkageError 链接错误

NoClassDefNotFoundError 类定义未找到错误

(3) java.awt.AWTError 图形界面错误

(七) 使用 try…catch 语句处理异常

1.异常类型匹配的处理方式

(1)程序功能:首先说明"这是一个异常处理的例子",然后在程序中主动产生一个

ArithmeticException 类型被 0 除的异常,并用 catch 语句捕获这个异常。 后通过

ArithmeticException 类的对象 e 的方法 getMessage 给出异常的具体类型并显示出来。

(2)编写使用 try…catch 语句处理异常的程序文件 LX4_6.java,源代码如下。

public class LX4_6{

public static void main(String[] arg3) {

System.out.println("这是一个异常处理的例子\n");

try {

int i=10;

i /=0;

}

catch (ArithmeticException e) {

System.out.println("异常是:"+e.getMessage());

}

finally {

System.out.println("finally 语句被执行");

}

}

}

(3)编译并运行程序,结果如图 4.7 所示。

70

图 4.7

注意:如果在 catch 语句中声明的异常类是 Exception,catch 语句也能正确地捕获,这是因为

Exception是ArithmeticException的父类。如果不能确定会发生哪种情况的异常,那么 好指定catch

的参数为 Exception,即说明异常的类型为 Exception。

2.异常类型不匹配的程序

(1)编写一个 catch 语句中声明的异常类型不匹配的程序 LX4_7.java,源代码如下。

public class LX4_7{

public static void main(String[] args) {

System.out.println(“这是一个异常处理的例子\n”);

try {

int i=10;

i /=0;

}

catch (IndexOutOfBoundsException e) {

System.out.println("异常是:"+e.getMessage());

}

finally {

System.out.println("finally 语句被执行");

}

}

}

(2)编译并运行程序 LX4_7,结果如图 4.8 所示。

因为 LX4_7 程序试图捕获一个异常类为 IndexOutOfBoundsException 的异常,但发生的异常却是

ArithmeticException 类,所以,程序可以通过编译但在运行时,系统会给出异常报告:报告所发生

的但没有被捕获的异常。不过在此之前,其它语句和 finally 语句将会被执行。

71

图 4.8

提示:该程序表明,如果试图捕获一个不同类型的异常,将会发生意想不到的情况。

3.包含多个 catch 子句的异常处理程序

(1)程序功能:在 try 子句中设计两个可能出现的异常,当 a 为 0 时会发生异常。另外一个是肯

定的异常,因为数组 c 的长度为 1,定义 c[42]是为法的。通过两个 catch 子句分别来捕获异常。

(2)编写包含多个 catch 子句的 LX4_8.java 程序,源代码如下。

public class LX4_8{

public static void main(String[] args) {

try {

int a=args.length;

System.out.println("\na = "+a);

int b=42/a;

int c[]={1};

c[42]=99;

}

catch (ArithmeticException e) {

System.out.println("发生了被 0 除:"+e);

}

catch (ArrayIndexOutOfBoundsException e) {

System.out.println("数组下标越界:"+e);

}

}

}

(2)实验下面两种情况:

1) 在程序运行时不输入参数,则 args.length 的值为 0,这将引起一个被 0除异常。其结果

如图 4.9 所示。

72

图 4.9

2) 在运行程序时,输入 22,将不会引起被 0 除异常,但会引起一个另一个异常即数组下标

越界 ArrayIndexOutOfBoundsException。因为整型数组只有一个元素 c[0],程序中却要

使用 c[42],这将发生数组下标越界。运行结果如图 4.10 所示。

图 4.10

(八) 使用 throw 语句抛出异常

1. throw 语句的作用

在上面的实验中,可以发现,异常对象是 Java 运行时由系统抛出的。抛出异常也可以通过使用

throw 语句实现。throw 是 Java 语言的关键字,用来告知编译器此处要发生一个异常。throw 后面要

跟一个新创建的异常类对象,用于指出异常的名称和类型。

throw 语句格式为:

<throw> <new> <异常对象名()>;

73

程序会在 throw 语句处立即终止,转向 try…catch 寻找异常处理方法,不再执行 throw 后面的语

句。

2. throw 语句的使用

(1)编写带有 throw 语句的程序 TC5.java,源代码如下。

public class LX4_9 {

static void throwProcess() {

try {

throw new NullPointerException("空指针异常");

}

catch (NullPointerException e) {

System.out.println("\n 在 throwProcess 方法中捕获一个"+e.getMessage());

throw e;

}

}

public static void main(String args[]) {

try {

throwProcess();

}

catch (NullPointerException e) {

System.out.println("再次捕获:"+e);

}

}

}

(2)编译并运行程序,结果如图 4.11 所示。

图 4.11

(3)程序执行流程

程序首先调用 throwProcess 方法,明确地抛出了一个 NullPointerException 异常并将其命名为

74

“空指针异常”。然后程序流程将转向throwProcess方法中的catch子句,输出一条信息。throwProcess

方法的 catch 子句又抛出了一个同样的异常 e。然后结束 throwProcess 方法的调用,执行 main 方法

中的 catch 子句,再次捕获这个异常。

(九) 使用 throws 子句

1.throws 子句的作用

throws 子句一般用来表明在使用该方法时可能抛出异常但不捕获的异常。异常由系统来处理。

throws 子句也可以指出抛出异常是 RuntimeException 或自定义异常类,即异常的类型,以便准

备调用其它方法捕获它,这种情况一般需要两个方法来分别处理抛出异常和处理异常。

2.只是在方法中抛出异常的程序

对于程序中无法处理的异常,可以使用 throws 子句在方法中抛出异常交由系统处理。

(1)程序功能:在程序中打开文件 a3.txt,因为该文件可能不存在或路径不对,所以存在

IOException 类型异常的可能,因此这里使用 throws 来抛出异常。

(2)编写只是抛出异常的程序文件 LX4_10.java,源代码如下。

import java.io.*;

public class LX4_10

{

public static void main (String args[]) throws IOException

{

FileInputStream fis = new FileInputStream("a3.txt");

}

}

(2)编译并运行程序,如果该文件在当前目录中不存在,将由系统自动给出异常报告,如图 4.12

所示。

图 4.12

75

3.带有捕获处理的 throws 子句

(1)程序功能:在这个程序中的 mathod 方法中使用 throws 子句抛出异常,在 main 方法中捕获

处理异常。

(2)TC6.java,源代码如下。

import java.io.*;

public class LX4_11{

static void mathod() throws IllegalAccessException {

System.out.println("\n 在 mathod 中抛出一个异常");

throw new IllegalAccessException();

}

public static void main(String args[]) {

try {

mathod();

}

catch (IllegalAccessException e) {

System.out.println("在 main 中捕获异常:"+e);

}

}

}

(3)编译并运行程序,结果如图 4.13 所示。

图 4.13

(十) 使用 finally 子句

1. finally 子句的作用

当一个异常被抛出时,程序的执行流程就不再是连续的了,会跳过某些语句,甚至会由于没有与

之匹配的 catch 子句而过早地返回,结束程序的运行。为了确保一段代码不管发生什么异常都能被执

行,可以使用 finally 子句。每个 try 语句至少都要有一个与之相配的 catch 或 finally 子句。

从一个方法中返回到调用它的另外一个方法,可以通过 return 语句或通过一个没有被捕获的异

76

常,但 finally 子句总是在返回前被执行。

2. 创建使用 finally 子句的程序文件 LX4_12.java。

(1)程序功能:在类 LX4_12 的 mathodA 方法中使用 try 子句捕获异常,使用 finally 子句处理

异常。在类 LX4_11 的 main 方法中使用 try 子句捕获 mathodA 异常,

(2)编写 LX4_12.java 程序,源代码如下。

class LX4_12{

static void mathodA() {

try {

System.out.println("\nmathodA 抛出一个异常");

throw new RuntimeException();

}

finally {

System.out.println("执行 mathodA 的 finally");

}

}

static void mathodB() {

try{

System.out.println("mathodB 正常返回");

return;

}

finally {

System.out.println("执行 mathodB 的 finally");

}

}

public static void main(String args[]) {

try {

mathodA();

} catch (Exception e) {

mathodB();

}

}

}

(3)编译并运行该程序,,结果如图 4.14 所示。

77

图 4.14

注意:对于程序中需要处理的异常,一般要编写 try-catch-finally 语句捕获并处理。

(十一) 创建自定义异常类

1.创建自定义异常类程序文件 LX4_13.java

(1)程序功能:通过继承 Exception 异常类创建一个自定义异常类 MyException,然后再创建一

个主类 LX4_13 使用自定义异常类 MyException。

(2)编写 LX4_13.java 程序文件,源代码如下。

class MyException extends Exception {

private int x;

MyException(int a) {

x=a;

}

public String toString() {

return "自定义异常类 MyException";

}

}

public class LX4_13 {

static void mathod(int a) throws MyException { // 声明方法会抛出 MyException

System.out.println("\t 此处引用 mathod ("+a+")");

if (a>10) throw new MyException(a); // 主动抛出 MyException

System.out.println("正常返回");

}

public static void main(String args[]) {

try {

System.out.println("\n 进入监控区,执行可能发生异常的程序段");

78

mathod(8);

mathod(20);

mathod(6);

}

catch (MyException e) {

System.out.println("\t 程序发生异常并在此处进行处理");

System.out.println("\t 发生的异常为:"+e.toString());

}

System.out.println("这里可执行其它代码");

}

}

(3)编译并运行程序,结果如图 4.15 所示。

图 4.15

四、思考题

1. 包有什么作用?Java 系统有哪些类型的包?如何在程序中使用 Java 系统包中的类?

2. 如何创建包含四个自己创建的类的自定义包,如何使用这四个类。

3. 根据网上浏览的情况,说出 Object 类的几个成员方法。

4. 接口有什么作用?如何实现系统接口。

5. 如何创建一个自定义接口?如何在一个类中实现这个接口?

6. 什么是异常?异常处理机制有什么作用?异常处理有哪些方式。

79

实验 5 常用系统类的使用

一、 实验目的

了解 Java 常用的系统类,包括 Java Applet、字符串类、输入输出流类、数学函数类、日期类、随机

数类以及向量类等的基本使用方法。理解 Java 系统类的构成。

二、 实验要求

1. 进一步了解 Applet 类。

2. 掌握字符串类的使用方法。

3. 掌握不同类型的输入输出流类,标准数据流、文件流、数据输入输出流、对象流等。

4. 掌握数学函数类的使用方法。

5. 掌握日期类的使用方法。

6. 掌握向量类的使用方法。

三、 实验内容

(一) 了解 Applet 的生命周期

程序运行从开始大结束的过程称为程序的生命周期。独立应用程序的生命周期从 main()方法开

始,直到运行结束。而 Applet 应用程序的生命周期与浏览器相关。作为浏览器的一部分,Applet 程

序何时运行,何时结束都由浏览器控制,Applet 对象只是作为浏览器窗口中运行的一个线程。浏览器

与 Applet 具有如下关系。

在浏览器中打开包含 Applet 对象的页面时,创建并初始化其中的 Applet 对象。

显示 Applet 时,启动 Applet 线程运行。

不显示 Applet 时,停止 Applet 线程运行。

在浏览器中关闭页面窗口时,销毁 Applet 对象。

与此相应,Applet 类中声明了与生命周期相关的 4 个方法:init()、start()、stop()、destroy

()。4 个方法代表 Applet 的 4 个活动阶段。

1.创建揭示 Applet 生命周期的程序 LX5_1.java。

(1)程序功能:本程序包含 Applet 的 4 个与生命周期相关的方法 init()、start()、stop()、

80

destroy()。程序中创建了自定义方法 addWords()来显示相应的字符串。addWords 方法首先在标准

输出即屏幕上显示字符串参数,然后将字符串添加到字符串缓冲区 buffer,通过调用 repaint 方法重

画页面,首先自动调用 updata 方法将当前画面清空,然后再调用 paint 方法在指定位置显示字符串。

(2)编写 LX5_1.java 程序文件,源代码如下。

import java.applet.Applet;

import java.awt.Graphics;

public class LX5_1 extends Applet {

StringBuffer buffer=new StringBuffer();

public void init() {

addWords("执行了初始化方法 init()...");

}

public void start() {

addWords("执行了开始方法 start()...");

}

public void stop() {

addWords("执行了停止方法 stop()...");

}

public void destroy() {

addWords("执行了清除方法 destroy()...");

}

void addWords(String s) {

System.out.println(s);

81

buffer.append(s);

repaint();

}

public void paint(Graphics g) {

g.drawString(buffer.toString(),5,15);

}

}

2.编译 LX5_1.java 文件。

3.编写显示 LX5_1.class 的页面文件 LX5_1.html,代码如下。

<html>

<applet codebase=e:/java/程序 code=LX5_1.class width=300 height=120>

</applet >

</html>

4.在命令提示符窗口调用小程序查看器浏览 LX5_1.html 页面观察 Applet 应用程序,其结果

如图 5.1 所示。在图 5.2 所示的命令提示符窗口可以看到,在打开 LX5_1.html 时,出现了如图

5.1 所示的情况,表示执行了初始化方法和开始方法。当关闭 LX5_1.html 时,在命令提示符窗口

可以看到如图 5.2 所示执行停止和销毁方法。

图 5.1

82

图 5.2

5.程序分析:本程序不仅揭示了与生命周期相关的 4 个方法,还揭示了 Applet 显示和刷新的 3

个方法:paint()、repaint()和 updata()方法。Applet 的显示和刷新由一个独立线程控制,称

为 AWT 线程。AWT 线程的处理机制有两种情况。

(1)自动执行 paint 方法重新绘图

如果程序中重写 paint()方法,当浏览器运行时,AWT 线程将自动在 Applet 上绘制图形;或者

Applet 内容被覆盖,当其他窗口关闭或移开时,AWT 线程会自动调用 paint 方法,重画曾被覆盖的部

分。

(2)调用 repaint 方法重新绘图

程序中如果需要重新绘图,可以调用 repaint 方法,AWT 线程会自动调用 updata 方法首先清空当

前页面,然后调用 paint 方法重新绘制图形。

(二) 使用字符串与字符串类

java.lang 有两个字符串类 String 和 StringBuffer,封装了字符串的全部操作。其中 String 用

来处理创建以后不再改变的字符串,StringBuffer 用来处理可变字符串。String 和 StringBuffer 为

终类,不能派生子类,可以防止用户修改。String 和 StringBuffer 类在运行时要经历严格的边界

条件检验,可以自动捕获异常,可以提高程序的健壮性。

1.创建使用 String 和 StringBuffer 类的程序

(1)程序功能:实现字符串的翻转。

(2)编写 LX5_2.java 程序文件,源代码如下。

import java.applet.Applet;

import java.awt.Graphics;

public class LX5_2 extends Applet {

public void paint(Graphics g) {

String str="这是一个字符串——This is a test string";

83

g.drawString("正常字符串:"+str, 30, 30);

g.drawString("翻转字符串:"+reverse(str), 30, 60);

}

public String reverse(String s) {

int len=s.length();

StringBuffer buffer=new StringBuffer(len);

for (int i=len-1; i>=0; i--)

buffer.append(s.charAt(i));

return buffer.toString();

}

}

2.编译 LX5_2.java 程序文件。

3.编写显示 LX5_2.class 的页面文件 LX5_2.html,源代码如下。

<html>

<applet codebase=e:/java/程序 code=LX5_2.class width=400 height=120>

</applet >

</html>

4.在浏览器打开 LX5_2.html 文件,结果如图 5.3 所示。

图 5.3

5. 程序分析:

程序在 paint 方法中首先定义一个 String 类对象 str, 将"This is a test string" 将字符串

常量赋给了 str(实际的程序流程为 Java 系统先为字符串常量创建一个无名字符串对象,然后再把字

84

符串的引用赋给 str)。然后使用 Graphics 的对象 g,调用 drawString 方法输出原始字符串,然后输

出翻转后的字符串,对字符串的翻转操作使用自定义的 reverse 方法实现。在 drawString 方法里有一

个字符串表达式,将字符串常量和字符串变量进行了连接(+)运算,其结果仍为字符串对象,字符串

连接是 String 类的唯一运算操作。drawString(字符串对象,x坐标,y 坐标)方法将字符串按定义

的位置在 Applet 中显示出来。

在 reverse 方法中,创建了 StringBuffer 对象 buffer,在创建时指定其长度为字符串参数 s 的

长度。程序中使用了 String 类的方法 charAt(i)(可返回字符串的第 i 个字符),使用了 StringBuffer

类的方法 append 连接字符串(可将参数值添加到字符串尾部)。在 for 循环中,每次反向从字符串 s

中取出一个字符添加到 buffer 的尾部。循环完毕,buffer 中存放的就是翻转后的字符串。因为 reverse

方法的返回值是 String 类型,因此还调用了 toString 方法将 StringBuffer 类型转换成 String 类型

再返回。

(三) 使用输入输出流类

1. 使用标准数据流的应用程序

标准数据流指在字符方式下(如 DOS 提示符)程序与系统进行输入输出的方式,键盘和显示器屏

幕是标准输入输出设备,数据输入的起点为键盘,数据输出的终点是屏幕,输出的数据可以在屏幕上

显示出来。

(1) 程序功能:将键盘上输入的字符在屏幕上显示出来。

(2) 编写 LX5_3.java 程序文件,源代码如下。

class LX5_3{

public static void main(String[] args) throws java.io.IOException {

byte buffer[]=new byte[10];

System.out.println("从键盘输入不超过 10 个字符,按回车键结束输入:");

int count =System.in.read(buffer);//读取输入的字符并存放在缓冲区 buffer 中

System.out.println("保存在缓冲区 buffer 中元素的个数为:"+count);

System.out.println("buffer 中各元素的值为:");

for (int i=0;i<count;i++){

System.out.print(" "+ buffer[i]);//在屏幕上显示 buffer 元素的值

}

System.out.println();

System.out.println("输出 buffer 字符元素:");

System.out.write(buffer, 0, buffer.length);

}

}

(3)编译 LX5_3.java 文件。

85

(4)在命令提示符窗口运行 LX5_3.class 文件,并输入 1234,结果如图 5.4 所示。

图 5.4

思考:为什么缓冲区 buffer 中元素的个数为显示的是 6?

2. 使用文件输入输出流的应用程序

(1) 程序功能:将保存在本地机当前文件夹中的 LX5_1.HTML 文本文件的内容在屏幕上显示出

来,然后将其另存为 LX5_1.txt 文件。

(2) 编写 LX5_4.java 程序文件,源代码如下。

import java.io.*;

public class LX5_4 {

public static void main(String[] args) throws IOException {

FileReader in=new FileReader("LX5_1.HTML");//建立文件输入流

BufferedReader bin=new BufferedReader(in);//建立缓冲输入流

FileWriter out=new FileWriter(" LX5_1.txt",true);//建立文件输出流

String str;

while ((str=bin.readLine())!=null) {

//将缓冲区内容通过循环方式逐行赋值给字符串 str

System.out.println(str);//在屏幕上显示字符串 str

out.write(str+"\n");//将字符串 str 通过输出流写入 LX5_1.txt 中

}

in.close();

out.close();

}

}

(3) 编译并运行程序,结果如图 5.5 所示。

86

图 5.5

(4) 在当前文件夹中找到 LX5_1.txt 文件并打开,可看到如图 5.6 所示内容。再运行一次程序,

看看会发生什么变化。

图 5.6

(5) 总结:程序中使用了哪些数据流类,建立数据流的步骤。

3. 使用随机文件类的应用程序

使用文件输入类 FileReader 只能将文件内容全部读入。如果要选择读入文件的内容,可使用随机

文件类 RandomAccessFile。

(1) 程序功能:建立数据流,通过指针有选择的读入文件内容。

(2) 编写 LX5_5.java 程序文件,源代码如下。

import java.io.*;

class LX5_5 {

public static void main(String args[]) {

String str[]={"First line\n","Second line\n","Last line\n"};

try {

RandomAccessFile rf=new RandomAccessFile("LX5_5.txt", "rw");

System.out.println("\n 文件指针位置为:"+rf.getFilePointer());

System.out.println("文件的长度为:"+rf.length());

rf.seek(rf.length());

System.out.println("文件指针现在的位置为:"+rf.getFilePointer());

for (int i=0; i<3; i++)

rf.writeChars(str[i]); // 字符串转为字节串添加到文件末尾

87

rf.seek(10);

System.out.println("\n 选择显示的文件内容:");

String s;

while ((s=rf.readLine())!=null)

System.out.println(s);

rf.close();

}

catch (FileNotFoundException fnoe) {}

catch (IOException ioe) {}

}

}

(3)编译并运行程序,结果如图 5.7 所示。

图 5.7

思考:本程序中的数据流 rf 有什么特点?

4. 使用数据输入输出流与文件输入输出流类的应用程序

使用数据输入流DataOutputStream和数据输出流DataInputStream可以读取或写入任何Java类型

的数据,不用关心它们的实际长度是多少字节。一般与文件输入流 FileInputStream 和输出流类

FileOutputStream 一起使用。

(1) 程序功能:将整型数据和字符串对象通过数据输出流写到文件中。将文件中的整型数据和

字符串对象通过数据输出流读出,并在屏幕上显示文件中的内容。

(2) 编写 LX5_6.java 程序文件,源代码如下。

import java.io.*;

public class LX5_6

{

88

public static void main(String arg[])

{

try

{ //添加方式创建文件输出流

FileOutputStream fout = new FileOutputStream("LX5_6.txt",true);

DataOutputStream dout = new DataOutputStream(fout);

dout.writeInt(1);

dout.writeChars("罗马"+"\n");

dout.writeInt(2);

dout.writeChars("北京"+"\n");

dout.close();

}

catch (IOException ioe){}

try

{

FileInputStream fin = new FileInputStream("LX5_6.txt");

DataInputStream din = new DataInputStream(fin);

int i = din.readInt();

while (i!=-1) //输入流未结束时,输入流结束时 i 为-1

{

System.out.print(i+" ");

char ch ;

while ((ch=din.readChar())!='\n') //字符串未结束时

System.out.print(ch);

System.out.println();

i = din.readInt();

}

din.close();

}

catch (IOException ioe){}

}

}

(3) 编译并运行程序,结果如图 5.8 所示。

89

图 5.8

思考:数据输入输出流的特点。

5. 使用对象输入输出流的应用程序

使用对象流可以直接写入或读取一个对象。由于一个类的对象包含多种信息,为了保证从对象流

中能够读取到正确的对象,因此要求所有写入对象流的对象都必须是序列化的对象。一个类如果实现

了 Serializable 接口,那么这个类的对象就是序列化的对象。Serializable 接口没有方法,实现该

接口的类不需要实现额外的方法。

(1) 程序功能:保存对象信息到文件,并将文件中的对象信息显示出来。

(2) 编写 LX5_7.java 程序文件,源代码如下。

import java.io.*;

public class LX5_7 implements Serializable //序列化接口

{

int bh=1;int nl=21;

String xm;

LX5_7(int bh,String xm,int nl)//构造方法

{

this.bh = bh;

this.xm = xm;

this.nl = nl;

}

LX5_7()//构造方法

{

this(0,"",21);

}

void save(String fname)//保存到文件中的方法

{

try

{

FileOutputStream fout = new FileOutputStream(fname);//输出文件流

ObjectOutputStream out = new ObjectOutputStream(fout);//输出对象流

out.writeObject(this); //写入对象

90

out.close();

}

catch (FileNotFoundException fe){}

catch (IOException ioe){}

}

void display(String fname)//显示文件中对象信息的方法

{

try

{

FileInputStream fin = new FileInputStream(fname);//输入文件流

ObjectInputStream in = new ObjectInputStream(fin);//输入对象流

LX5_7 OO = (LX5_7)in.readObject(); //读取对象

System.out.println(" 类 名 : "+OO.getClass().getName()+"

"+OO.getClass().getInterfaces()[0]);

System.out.println(" "+OO.bh+" "+OO.xm+" "+OO.nl);

in.close();

}

catch (FileNotFoundException fe){}

catch (IOException ioe){}

catch (ClassNotFoundException ioe) {}

}

public static void main(String arg[])

{

String fname = "LX5_7.obj";

LX5_7 O1= new LX5_7(1,"张驰",14);

O1.save(fname);

O1.display(fname);

}

}

(3) 编译并运行程序,结果如图 5.9 所示。

图 5.9

(4) 程序分析:首先创建一个实现 Serializable 接口的类 LX5_7,其包含 3 个成员变量 bh(编

91

号)、xm(姓名)、nl(年龄);两个构造方法;一个使用对象流保存对象信息的 save 方法,

一个使用对象流输出的对象信息的 display 方法。在 main 主方法中创建 LX5_7 类的对象

O1,然后使用其保存与显示的方法。

(四) 使用数学函数类

Math 是一个 终类,含有基本数学运算函数,如指数运算、对数运算、求平方根、三角函数、随

机数等,可以直接在程序中加 Math.前 调用。

1. 创建使用 Math 类的应用程序 LX5_8.java,源程序如下。

import java.util.*;

class LX5_8 {

public static void main(String args[]) {

Random r1=new Random(1234567890L);

Random r2=new Random(1234567890L);

boolean b=r1.nextBoolean(); // 随机数不为 0 时取真值

int i1=r1.nextInt(100); // 产生大于等于 0 小于 100 的随机数

int i2=r2.nextInt(100); // 同上

double i3=r1.nextDouble(); // 产生大于等于 0.0 小于 1.0 的随机数

double i4=r2.nextDouble(); // 同上

double d1=Math.sin(Math.toRadians(30.0));

double d2=Math.log(Math.E);

double d3=Math.pow(2.0, 3.0);

int r=Math.round(33.6F);

System.out.println("b 的随机数不为 0 时 "+b);

System.out.println("i1 的随机数为 "+i1);

System.out.println("i2 的随机数为 "+i2);

System.out.println("d1 的随机数为 "+i3);

System.out.println("d2 的随机数为 "+i4);

System.out.println("30 弧度的正弦值:Math.sin(Math.toRadians(30.0))= "+d1);

System.out.println("E 的对数值:Math.log(Math.E)= "+d2);

System.out.println("2 的 3 次方:Math.pow(2.0, 3.0)= "+d3);

System.out.println("33.6F 四舍五入:Math.round(33.6F)= "+r);

92

}

}

2. 编译并运行程序,结果如图 5.10 所示。

图 5.10

(五) 使用日期类

Java 提供了 3 个日期类:Date、Calendar 和 DateFormat。其中,Date 类主要用于创建日期对象

并获取日期,Calendar 类可获取和设置日期,DateFormat 类用来设置日期的格式。

Java 语言规定的基准日期为 1970.1.1 00:00:00 格林威治(GMT)标准时间,当前日期是由基准

日期开始所经历的毫秒数转换出来的。

1. 使用日期类的 Applate 应用程序

(1)程序功能:说明 3 个日期类 Date、Calendar 和 DateFormat 的使用方式及显示的样式。

(2)编写 LX5_9.java 程序文件,源代码如下。

import java.text.*;

import java.util.*;

import java.awt.*;

import java.applet.*;

public class LX5_9 extends Applet {

public void paint(Graphics g) {

Date today;

Calendar now;

DateFormat f1,f2;

String s1,s2;

today=new Date(); // 获取系统当前日期

g.drawString("字符串格式:"+today.toString(),20,20);

93

f1=DateFormat.getInstance(); // 以默认格式生成格式化器

s1=f1.format(today); // 将日期转换为字符串

g.drawString("系统格式:"+s1,20,40);

// 生成长格式的中国日期格式化器

f1=DateFormat.getDateInstance(DateFormat.LONG, Locale.CHINA);

// 生成长格式的中国时间格式化器

f2=DateFormat.getTimeInstance(DateFormat.LONG, Locale.CHINA);

s1=f1.format(today); // 将日期转换为日期字符串

s2=f2.format(today); // 将日期转换为时间字符串

g.drawString("中国格式:"+s1+" "+s2,20,60);

now=Calendar.getInstance(); // 获取系统时间

s1=now.get(now.HOUR)+" 时 " +now.get(now.MINUTE)+" 分 "

+now.get(now.SECOND)+"秒";

g.drawString("调整前时间:"+s1,20,80);

now.set(2004,8,15,9,9,9);

today=now.getTime();

g.drawString("调整后时间:"+today.toString(),20,100);

}

}

(3)编译程序文件。

(4)在浏览器中打开包含应用程序的页面文件,显示结果如图 5.11 所示。

图 5.11

94

2. 在独立运行的应用程序中使用日期函数。

(1)程序功能:补充说明 3 个日期类 Date、Calendar 和 DateFormat 的使用方式及显示的样式。

(2)编写 LX5_10.java 程序文件,源代码如下。

import java.util.*;

import java.text.*;

public class LX5_10

{

public static void main (String args[])

{

Date today = new Date(); //当前日期和时间

SimpleDateFormat sdf;

sdf= new SimpleDateFormat("yyyy 年 MM 月 dd 日 hh 时 mm 分 ss 秒 a EEEEE");

System.out.println("当前日期和时间: "+sdf.format(today));

long hms=System.currentTimeMillis(); //当前时间的毫秒数

System.out.println("当前时间的毫秒数="+hms);

Date tomorrow = new Date(hms+24*60*60*1000);

System.out.println("明天是"+sdf.format(tomorrow));

Calendar now = Calendar.getInstance();

int year =now.get(Calendar.YEAR); //年份

int month=now.get(Calendar.MONTH)+1; //月份

int day = now.get(Calendar.DATE); //日期

System.out.print("今天是"+year+"年"+month+"月"+day+"日");

int week = now.get(Calendar.DAY_OF_WEEK); //星期

switch (week)

{

case 1: System.out.println(" 星期日");break;

case 2: System.out.println(" 星期一");break;

case 3: System.out.println(" 星期二");break;

case 4: System.out.println(" 星期三");break;

case 5: System.out.println(" 星期四");break;

case 6: System.out.println(" 星期五");break;

case 7: System.out.println(" 星期六");break;

}

95

}

}

(3)编译并运行程序,结果如图 5.12 所示。

图 5.12

(六) 使用向量类 Vector

大多数编程语言中的数组是固定长度的,即数组一经建立就不能在使用过程中改变其长度。Java

引入 Vector 类来创建可以改变长度的变量。Vector 被设计成一个能不断增长的序列,它类似于可变

长数组,但功能更加强大,因为任何类型的对象都可以放入 Vector 类的对象中。通过调用 Vector 封

装的方法,可以随时添加或删除向量元素,以及增加或缩短向量序列的长度。

1.创建使用 Vector 向量类的应用程序

(1)程序功能:创建一个 Vector 对象 v,先通过键盘为 args[]输入两个分量,然后赋值给对象 v,

并通过直接方式为其分量赋值。

(2)编写 LX5_11.java 程序文件,源代码如下。

import java.util.*;

public class LX5_11{

public static void main(String args[]) {

Vector v=new Vector(1,1);

v.addElement(args[0]); //在向量尾部添加元素

v.addElement(args[1]);

v.addElement("3"); //在向量尾部添加元素

v.insertElementAt("0",0);//在指定位置插入元素

v.insertElementAt("aaa 字符串元素",3);

v.setElementAt("4",4);//替换指定位置的元素

v.addElement("5");

System.out.println("第 4 号元素为:"+v.elementAt(4));

Enumeration enum=v.elements();//枚举化对象,以便逐个取出元素

StringBuffer buffer=new StringBuffer();//字符串缓冲区

while(enum.hasMoreElements())

buffer.append(enum.nextElement()).append(",");

96

buffer.deleteCharAt(buffer.length()-1);

System.out.println("向量 v 的所有元素:"+buffer.toString()+"\n");

System.out.println("向量 v 的元素个数="+v.size()+" v 的长度为:"+v.capacity()+"\n");

v.removeAllElements();

System.out.println("删除后元素个数:"+v.size()+" 向量 v 长度:"+v.capacity()+"\n");

}

}

2.编译并运行程序,结果如图 5.13 所示。

图 5.13

97

实验 6 建立图形用户界面

一、 实验目的

了解图形用户界面基本组件窗口、按钮、文本框、选择框、滚动条等的使用方法,了解如何使用

布局管理器对组件进行管理,以及如何使用 Java 的事件处理机制。

二、 实验要求

1. 掌握在 Applet 容器中添加组件的方法,掌握使用布局管理器对组件进行管理的方法。

2. 理解 Java 的事件处理机制,掌握为不同组件编写事件处理程序的方法。

3. 掌握编写独立运行的窗口界面的方法。

4. 了解 Java Swing 组件的使用方法。

5. 了解对话框的使用方法。

三、 实验内容

(一) 创建图形用户界面

图形用户界面(Graphic User Interface ,简称 GUI)是为方便用户使用设计的窗口界面,在图

形用户界面中用户可以看到什么就操作什么,取代了在字符方式下知道是什么后才能操作什么的方式。

组件(Component)是构成 GUI 的基本要素,通过对不同事件的响应来完成和用户的交互或组件之间的

交互。组件一般作为一个对象放置在容器(Container)内,容器是能容纳和排列组件的对象,如 Applet、

Panel(面板)、Frame(窗口)等。通过容器的 add 方法把组件加入到容器中。

1. 在 Applet 中添加标签、按钮并使用网格布局

(1) 程序功能:在 Applet 容器中添加组件标签、按钮,并使用网格布局管理器排列组件在容

器中的位置。

(2) 编写 LX6_1.java 程序文件,源代码如下。

import java.awt.*;

import java.applet.Applet;

public class LX6_1 extends Applet {

Label l1;

Button b1, b2, b3, b4, b5, b6;

98

public void init() {

setLayout(new GridLayout(3,3)); // 设置网格布局(3行 3 列共 9个网格)

l1=new Label("标签 1");

b1 = new Button("按钮 1");

b2 = new Button("按钮 2");

b3 = new Button("按钮 3");

b4 = new Button("按钮 4");

add(l1);

add(b1);

add(b2);

add(b3);

add(new Label());

add(b4);

add(new Button("按钮 5"));

add( new Button("按钮 6"));

add(new Label("标签 2"));

}

}

(3) 编译程序 LX6_1.java。

(4) 编写显示 Applet 的页面文件 LX6_1.html,在浏览器显示结果如图 6.1 所示。

图 6.1

思考:在网格布局中组件的大小是如何确定的?组件是如何确定排列顺序的?

99

2. 在面板中添加组件

(1) 程序功能:在 Applet 中添加面板容器,并分别在 Applet、面板容器中添加组件并使用不

同的布局管理方式。

(2) 编写 LX6_2.java 程序文件,源代码如下。

import java.awt.*;

import java.awt.Color;

import java.applet.Applet;

public class LX6_2 extends Applet {

public void init() {

//设置 底层的 Applet 容器为顺序布局

setFont(new Font("Arial",Font.PLAIN,20));

Label l=new Label("这是 底层的 Applet 容器中的标签",Label.CENTER);

add(l);

Panel panel1=new Panel();

add( panel1);

panel1.setBackground(Color.blue);

panel1.setForeground(Color.red);

panel1.setLayout(new BorderLayout());//设置边界布局

panel1.add("North", new Button("北"));

panel1.add("South", new Button("南"));

panel1.add("East", new Button("东"));

panel1.add("West", new Button("西"));

panel1.add("Center", new Label("这是在 Panel1 面板 中部添加的标签"));

Panel panel2=new Panel();

add( panel2);

panel2.setLayout(new GridLayout(3,1)); //设置网格布局

Choice c=new Choice ();//创建下拉式列表

c.addItem("北京");

c.addItem("上海");

c.addItem("天津");

Label l1=new Label("这是在 Panel2 面板中的标签");

Button b1=new Button("Panel2 中的按钮");

panel2.setBackground(Color.green);

panel2.add(l1);

100

panel2.add(b1);

panel2.add(c);

}

}

(3) 编译程序 LX6_2.java。

(4) 编写显示 Applet 的页面文件 LX6_2.html,在浏览器显示结果如图 6.2 所示。

图 6.2

思考:如何添加面板?如何在面板中添加组件?如何在面板中设置布局管理器?

(二) 了解事件处理机制

在图形用户界面中,程序和用户的交互是通过组件响应各种事件来实现的。例如,用户单击了一

个按钮,意味着发生了按钮的单击事件;选中下拉框中的一个选项,意味着发生了一个选项事件。在

Java 中能产生事件的组件叫做事件源,如按钮。如果希望对单击按钮事件进行处理,可给事件源(按

钮)注册一个事件监听器(如包含按钮的容器),如同签订了一个委托合同,当事件源发生事件时,事

件监听器就代替事件源对发生的事件进行处理,这就是所谓的委托事件处理机制。

1.单击按钮的事件处理程序

(1)程序功能:使用手工布局设置组件标签、按钮的位置,为按钮编写单击事件处理方法。当用

101

户用鼠标单击按钮时,会听到一声响声。

(2)编写 LX6_3.java 程序文件,源代码如下。

import java.awt.*;

import java.awt.event.*;

import java.applet.Applet;

public class LX6_3 extends Applet implements ActionListener { // 实现动作事件监听

接口

public void init() {

setLayout(null);//关闭默认的顺序管理布局

Label l=new Label("按一下按钮可听到响声!", Label.CENTER);

add(l);

l.setBounds(40,10,150,30);

Button b=new Button("按钮");

add(b);

b.setBounds(60,50,60,40);

b.addActionListener (this); // 注册事件源的动作监听者

}

public void actionPerformed(ActionEvent e) {//实现单击事件接口的方法

Toolkit.getDefaultToolkit ().beep(); //单击事件发生时作出的反应

}

}

(3)编译程序 LX6_2.java。

(4)编写显示 Applet 的页面文件 LX6_3.html,在浏览器显示结果如图 6.3 所示。

102

图 6.3

思考:具有事件处理功能的类有什么特点?

2. 选择复选框和单选框按钮的事件处理程序

(1) 程序功能:在 Applte 上创建复选框、单选框、文本区域、单行文本框等组件,并实现根

据用户输入的 10 进制数,选择不同选项可转换为 2、8、16 进制数。

(2) 编写 LX6_4.java 程序文件,源代码如下。

import java.applet.Applet;

import java.awt.*;

import java.awt.event.*;

public class LX6_4 extends Applet implements ItemListener {

TextArea area=new TextArea(6,30);//创建文本区

String Item[]={"2 进制","8 进制","16 进制","10 进制"};

Checkbox cb[]=new Checkbox[5];

Checkbox radio[]=new Checkbox[5];

Label l=new Label("输入 10 进制数");

TextField TF=new TextField(6);//创建单行文本框

public void init() {

add(l);add(TF);

add(area);

add(new Label(" 请选择进制:"));

for(int i=0; i<4; i++) {

cb[i]=new Checkbox(Item[i]);

103

add(cb[i]);

cb[i].addItemListener(this);

}

CheckboxGroup cbGroup=new CheckboxGroup();//创建单选框

add(new Label("请选择进制:"));

for(int i=0; i<4; i++) {

radio[i]=new Checkbox(Item[i],cbGroup,false);

add(radio[i]);

radio[i].addItemListener(this);

}

}

public void itemStateChanged(ItemEvent e) {

int x=Integer.parseInt(TF.getText());

if (e.getItem ()=="2 进制")

area.append ("你选择的是"+e.getItem ()+ Integer.toBinaryString(x)+"\n");

if (e.getItem ()=="8 进制")

area.append ("你选择的是"+e.getItem ()+ Integer.toOctalString(x)+"\n");

if (e.getItem ()=="16 进制")

area.append ("你选择的是"+e.getItem ()+Integer.toHexString(x)+"\n");

if (e.getItem ()=="10 进制")

area.append ("你选择的是"+e.getItem ()+x+"\n");

}

}

(3) 编译程序 LX6_4.java。

(4) 编写显示 Applet 的页面文件 LX6_4.html,在浏览器显示结果如图 6.4 所示。

104

图 6.4

(三)建立独立运行的窗口界面并使用匿名类

常使用的包含组件的容器是窗口,在 Java 中窗口由 Frame 类生成。

1.创建一个窗口界面

(1)程序功能:创建一个具有关闭功能的空白窗口。

(2)编写 LX6_5_W.java 程序文件,源代码如下。

import java.awt.*;

import java.awt.event.*;

public class LX6_5_W {

public static void main(String[] args) {

new LX6_5_W();

}

LX6_5_W(){

Frame f=new Frame("初始窗口");//创建窗口对象

f.setSize(350,200);//设置窗口大小

f.setVisible(true);//设置窗口是可视的

f.addWindowListener(new WindowAdapter() {//为窗口添加窗口事件适配器

public void windowClosing(WindowEvent e) {//关闭窗口事件的方法

System.exit(0);

}

105

});

}

}

(3)编译并运行程序,会出现一个界面窗口如图 6.5 所示。它可以 大化、 小化,单击×按钮可以

关闭该窗口。

图 6.5

思考:

(1)有几种创建窗口对象的方法?

(2)本程序在哪里使用了匿名类?如何创建匿名类?

2.在窗口中添加组件

(1)程序功能:在窗口中添加组件。

(2)编写 LX6_6.java 程序文件,源代码如下。

import java.awt.*;

import java.awt.event.*;

public class LX6_6 extends Frame implements ActionListener {

Button btn1, btn2;

TextField f,tf1,tf2;

TextArea Area;

LX6_6() {

super("添加组件的窗口");

addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

System.exit(0);

}

});

setSize(350,250); //设置窗口大小

106

setLocation(200,200);//设置窗口显示位置

setFont(new Font("Arial",Font.PLAIN,12)); //设置字体

setLayout(new FlowLayout());

Area=new TextArea (6,40);

tf1=new TextField(10); tf2=new TextField(10);

btn1=new Button("显示"); btn2=new Button("退出");

f=new TextField(20);

add(Area); add(new Label("用户名"));

add(tf1); add(new Label("电话"));

add(tf2); add(f); add(btn1); add(btn2);

tf1.addActionListener(this); tf2.addActionListener(this);

btn1.addActionListener(this); btn2.addActionListener(this);

show();

}

public static void main(String args[]) {

new LX6_6();

}

public void actionPerformed(ActionEvent e) {

if (e.getSource()==btn1)

f.setText("你按下了“" + e.getActionCommand() + "”按钮");

if (e.getSource()==tf1)

Area.append("用户名:"+tf1.getText()+"\n");

if (e.getSource()==tf2)

Area.append("电 话:"+tf2.getText()+"\n");

if (e.getSource()==btn2) {

for (int i=0; i<100000000; i++);

dispose();//只关闭当前窗口,注销该对象

}

}

}

(3)编译并运行程序,界面窗口如图 6.6 所示。

107

图 6.6

注意:文本区的事件处理方式。

3.为窗口添加菜单

(1)程序功能:在窗口中添加菜单栏,在菜单栏添加菜单项,并添加下拉菜单和 2 级菜单,通过选择

菜单项可以执行不同操作,如“打开”可打开 LX6_6 类生成的窗口。

(2)编写 LX6_7.java 程序文件,源代码如下。

import java.awt.*;

import java.awt.event.*;

public class LX6_7 extends Frame implements ActionListener {

Panel p=new Panel();

Button b=new Button("退出");

MenuBar mb=new MenuBar(); // 以下生成菜单组件对象

Menu m1=new Menu("文件");

MenuItem open=new MenuItem("打开");

MenuItem close=new MenuItem("关闭");

MenuItem exit=new MenuItem("退出");

Menu m12=new Menu("编辑");

MenuItem copy=new MenuItem("复制");

MenuItem cut=new MenuItem("剪切");

MenuItem paste=new MenuItem("粘贴");

Menu m2=new Menu("帮助");

108

MenuItem content=new MenuItem("目录");

MenuItem index=new MenuItem("索引");

MenuItem about=new MenuItem("关于");

LX6_7() {

super("添加菜单的窗口");

setSize(350,200);

add("South",p);

p.add(b);

b.addActionListener(this);

m1.add(open); // 将菜单项加入到菜单 m1 中

m1.add(close);

m1.addSeparator(); //在菜单中添加分隔条

m1.add(exit);

open.addActionListener(this); //给菜单项 open 注册事件监听器

exit.addActionListener(this);

mb.add(m1); // 将菜单 m1 加入到菜单栏 mb 中

m12.add(copy); m12.add(cut); m12.add(paste);

m1.add(m12);//将 m12 作为 2 级菜单添加到 m1 菜单项中

m2.add(content); m2.add(index); m2.addSeparator(); m2.add(about);

mb.add(m2);

setMenuBar(mb); // 设置菜单栏为 mb

show();// 显示组件

}

public static void main(String args[]) {

new LX6_7();

}

public void actionPerformed(ActionEvent e) {

if (e.getActionCommand()=="退出")

System.exit(0);

if (e.getActionCommand()=="打开")

new LX6_6();

109

}

}

(3)编译并运行程序,界面窗口如图 6.7 所示。

图 6.7

(四)使用 Swing 组件

在 Java 中,能够实现图形用户界面的类库有两个:java.awt 和 javax.swing。前者称为抽象窗口

工具库 AWT(Abstract Windows Toolkit),后者是 Java 基础类库 JFC(Java Foundation Classes)

的一个组成部分,它提供了一套功能更强、数量更多、更美观的图形用户界面组件。Swing 组件名称

和 AWT 组件名称基本相同,但以 J 开头,例如 AWT 按钮类的名称是 Button,在 Swing 中的名称则是

JButton。

1.在 JApplet 中添加 Swing 组件

(1)程序功能:在 JApplet 中添加 3 个带有图片的按钮和一个带有图片的标签。

(2)准备图片文件:在当前目录下建立一个 image 文件夹,存放 4 个图片文件,例如

PreviousArrow.gif。

(3)编写 LX6_8.java 程序文件,源代码如下。

import javax.swing.*;

import java.awt.*;

import java.awt.Color;

public class LX6_8 extends JApplet {

Container pane;

110

JPanel panel1,panel2;

JButton button1,button2,button3;

JLabel label;

public void init() {

pane=getContentPane();

panel1=new JPanel(new FlowLayout());

panel2=new JPanel(new FlowLayout());

ImageIcon icon = new ImageIcon("image/PreviousArrow.gif"," ");

button1=new JButton(icon);

button2=new JButton(new ImageIcon("image/go.GIF"));

button3=new JButton(new ImageIcon("image/NextArrow.gif"));

label=new JLabel("图像标签",

new ImageIcon("image/Candl02.gif"),SwingConstants.CENTER);

pane.setBackground(new Color(255,255,200));

panel1.setBackground(new Color(255,255,104));

panel2.setBackground(new Color(255,255,214));

button1.setToolTipText("向上翻页按钮");

button2.setToolTipText("跳转按钮");

button3.setToolTipText("向下翻页按钮");

pane.add("North",panel1);

pane.add(panel2,BorderLayout.SOUTH);

panel1.add(button1);

panel1.add(button2);

panel1.add(button3);

panel2.add(label);

}

}

(4)编译 LX6_8.java。

(5)编写显示 LX6_8.class 的页面文件。

(6)使用 appletviewer 查看程序,结果如图 6.8 所示。

111

图 6.8

2.在 JFrame 窗口中添加组件

(1)程序功能:创建 JFrame 窗口,并在其中添加工具栏。

(2)准备图片文件:在当前目录下建立一个 image 文件夹,存放 3 个图片文件,例如

PreviousArrow.gif。

(3)编写 LX6_9.java 程序文件,源代码如下。

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class LX6_9 extends JFrame implements ActionListener {

JButton button1,button2,button3;

JToolBar toolBar;

JTextArea textArea;

JScrollPane scrollPane;

JPanel panel;

public static void main(String[] args) {

new LX6_9();

}

public LX6_9() {

super("带有工具栏按钮的窗口");

addWindowListener(new WindowAdapter() {

112

public void windowClosing(WindowEvent e) {

System.exit(0);

}

});

button1=new JButton(new ImageIcon("image/PreviousArrow.gif"));

button2=new JButton(new ImageIcon("image/go.GIF"));

button3=new JButton(new ImageIcon("image/NextArrow.gif"));

button1.addActionListener(this);

button2.addActionListener(this);

button3.addActionListener(this);

toolBar=new JToolBar();

toolBar.add(button1);

toolBar.add(button2);

toolBar.add(button3);

textArea=new JTextArea(6,30);

scrollPane=new JScrollPane(textArea);

panel=new JPanel();

setContentPane(panel);

panel.setLayout(new BorderLayout());

panel.setPreferredSize(new Dimension(300,150));

panel.add(toolBar,BorderLayout.NORTH);

panel.add(scrollPane,BorderLayout.CENTER);

pack();

show();

}

public void actionPerformed(ActionEvent e) {

String s="";

if (e.getSource()==button1)

s="左按钮被单击\n";

else if (e.getSource()==button2)

113

s="中按钮被单击\n";

else if (e.getSource()==button3)

s="右按钮被单击\n";

textArea.append(s);

}

}

(4)编译 LX6_9.java。

(5)运行 LX6_9.class,产生的窗口界面如图 6.9 所示。

图 6.9

思考:

(1)JApplet 与 Applet 在添加组件时有什么不同?

(2)创建 Container 类的目的是什么?用什么方法得到 Container 类的对象?

(3)JApplet 与 Applet 的默认布局是什么?

(4)在顶层容器 JApplet、JFrame 中能否直接加入组件?

(五)使用自定义对话框与内部类

对话框是 GUI 中很常见的窗口对象,有着广泛的应用。对话框和普通窗口 大的不同就是对话框

是依附在某个窗口上,一旦它所依附的窗口关闭了,对话框也要随着关闭。Java 提供了 Dialog 类用

于制作自定义对话框,当需要改变一些数据或需要一个提示窗口时可使用自定义对话框。

1.创建自定义对话框的应用程序

(1)程序功能:创建一个带有文本区及“对话框”按钮的父窗口,单击“对话框”按钮可打开一

个自定义对话框,从中可以定义行和列的数值,关闭对话框其设置的设置会显示在父窗口的文本区中。

(2)编写 LX6_10.java 程序文件,源代码如下。

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

114

public class LX6_10 extends JFrame implements ActionListener {

int row=10, col=40;

JPanel p1=new JPanel(), p2=new JPanel();

JTextArea ta=new JTextArea("文本区行数:"+row+" 列数:"+col, row, col);

JScrollPane scrollPane=new JScrollPane(ta);

Button exit=new Button("关闭");

Button dialog=new Button("对话框");

JPanel panel=new JPanel();

LX6_10() {

setContentPane(panel);

setTitle("带有对话框的父窗口");

panel.setPreferredSize(new Dimension(500,200));

panel.setLayout(new BorderLayout());

panel.add("Center", p1); panel.add("South", p2);

p1.add(scrollPane);

p2.add(exit); p2.add(dialog);

exit.addActionListener(this);

dialog.addActionListener(this);

pack();

show();

//setVisible(true);

}

public static void main(String args[]) {

new LX6_10();

}

public void actionPerformed(ActionEvent e) {

if (e.getSource()==exit)

System.exit(0);

else {

MyDialog dlg=new MyDialog(this, true);

dlg.show();

115

}

}

class MyDialog extends Dialog implements ActionListener {

Label label1=new Label("请输入行数");

Label label2=new Label("请输入列数");

TextField rows=new TextField(50);

TextField columns=new TextField(50);

Button OK=new Button("确定");

Button Cancel=new Button("取消");

MyDialog(LX6_10 parent, boolean modal) {

super(parent,modal);

setTitle("自定义对话框");

setSize(260,140);

setResizable(false);

setLayout(null);

add(label1);

add(label2);

label1.setBounds(50,30,65,20);

label2.setBounds(50,60,65,20);

add(rows);

add(columns);

rows.setText(Integer.toString(ta.getRows()));

columns.setText(Integer.toString(ta.getColumns()));

rows.setBounds(120,30,90,20);

columns.setBounds(120,60,90,20);

add(OK);

add(Cancel);

OK.setBounds(60,100,60,25);

Cancel.setBounds(140,100,60,25);

OK.addActionListener(this);

Cancel.addActionListener(this);

}

116

public void actionPerformed(ActionEvent e) {

if(e.getSource()==OK) {

int row=Integer.parseInt(rows.getText());

int col=Integer.parseInt(columns.getText());

ta.setRows(row);

ta.setColumns(col);

ta.setText("文本区行数:"+row+" 列数:"+col);

show();

}

dispose();

}

}

}

2.编译并运行程序,在父窗口中单击“对话框”按钮会出现“自定义对话框”窗口,如图 6.10

所示窗口。设置对话框中参数,单击“确定”按钮,可关闭自定义对话框,并可看到父窗口中出现的

变化,如图 6.11 所示。

图 6.10

117

图 6.11

3.程序分析:本程序包括两个类,一个是程序的主类 LX6_10,另外一个是 MyDialog 类,它是 Dialog

(对话框)派生的子类,它是作为 LX6_10 的内部类创建的,内部类有一个好处就是可以随意访问主类

的成员。在 MyDialog 的构造方法中,以主类为父窗口调用了父类的构造方法,生成一个有模式对话框

窗口。

此外,MyDialog 类中采用了手工布局方式来安排各组件的位置。两个文本框用来显示和输入数值,

点击“确定”按钮后,用这两个数值设定主类中文本区的行列数。无论点击“确定”还是“取消”,

后都调用 dispose 方法来关闭自定义对话框。

四、 练习题

1.实验目的:图形界面设计。熟悉 AWT 包或 Swing 包中组件的使用方法,了解委托事件处理机制。

2.题意(可选做其中一题):

(1)设计一个在 Windows 系统中可以使用的“计算器”窗口并实现(+、-、×、%等)其功能。

(2)设计一个在 Windows 系统中可以使用的“日历器”窗口,根据界面提供的月、日、年选项,选择

当前时间并设置出当前时间。

3.要求

实现多种运算,保证运算正确,其运算结果或选择结果要显示在窗口界面上。

118

实验 7 图形与多媒体处理

一、 实验目的

熟悉图形、图像的使用方法,理解计算机动画的原理和 Java 的多线程处理机制,能够编写 Applet

中使用的动画。

二、 实验要求

1. 掌握使用图形类 Graphics 画出不同图形的方法。

2. 掌握在容器中输入图像、播放音乐的方法。

3. 理解计算机动画原理,掌握图形双缓冲技术,能够设计计算机动画。

4. 理解多线程机制,掌握线程的使用方法。

三、 实验内容

(一) 使用图形类 Graphics

在 Java 中基本图形包括点、线、圆、矩形等,是构成复杂图形的基础。绘制基本图形要使用 AWT

包中的 Graphics 类,它提供了各种基本图形的绘制方法,可以直接引用这些方法画点、线、圆、矩形

等。

1.创建在 Applet 上画出不同的图形的程序

(1)程序功能:在 Applet 上使用不同的颜色画出直线、圆、方块、圆弧等图形。

(2)编写 LX7_1.java 程序文件,源代码如下。

import java.applet.Applet;

import java.awt.Graphics;

import java.awt.Color;

public class LX7_1 extends Applet {

public void paint(Graphics g) {

119

g.drawLine(10,10,50,10);//画线(确定两点)

g.setColor(Color.red);//设置红颜色

g.drawOval(35,35,100,60);//画椭圆(圆心、宽和高)

g.fillOval(200,15,60,100);//画具有填充色的圆

g.setColor(Color.blue);//设置蓝颜色

g.drawRect(20,130,80,80);//画矩形

g.fillRect(120,130,80,80);//画具有填充色的矩形

g.drawRoundRect(220,130,80,80,20,20);//画圆角矩形

g.fillRoundRect(320,130,80,80,20,20);//画具有填充色的圆角矩形

g.setColor(new Color(255,255,0)); //设置黄颜色

g.drawArc (250,20,100,100,0,90);

g.fillArc (380,20,100,100,90,90);

g.fillArc (300,25,100,100,180,90);

g.drawArc (330,25,100,100,0,-90);

}

}

(3)编译程序 LX7_1.java。

(4)编写显示 LX7_1.class 的页面文件,在浏览器中显示结果如图 7.1 所示。

图 7.1

2.创建使用画布对象的 Applet 应用程序

120

(1)程序功能:创建一个带有多边形、圆的自定义画布类,在 Applet 上显示自定义画布的对象。

(2)编写 LX7_2.java 程序文件,源代码如下。

import java.applet.Applet;

import java.awt.*;

import java.awt.Color;

public class LX7_2 extends Applet {

public void init() {

Color col=new Color(20,55,75);

setBackground(col);//设置 Applet 的背景色

setForeground(Color.yellow);//设置 Applet 的前景色

MyCanvas1 c=new MyCanvas1();//创建画布对象

c.setBackground(Color.white);//设置画布的背景色

c.setSize(300,200);//设置画布的大小

add(c);

}

}

class MyCanvas1 extends Canvas {

public void paint(Graphics g) {

g.setColor(Color.red);

g.fillOval(40,20,80,80);//画圆

g.setColor(Color.cyan);//设置青色

int p1X[]={20,20,100,20};//多边形的 x 坐标

int p1Y[]={20,80,20,20};//多边形的 y 坐标

int p1=3;//多边形的边数

g.fillPolygon (p1X,p1Y,p1);//画填充多边形

int p2X[]={280,120,50,90,210,280};

int p2Y[]={20,50,100,110,70,20};

int p2=5;

g.drawPolygon (p2X,p2Y,p2);//画多边形

}

}

(3)编译程序 LX7_2.java。

(4)编写显示 LX7_2.class 的页面文件,在浏览器中显示结果如图 7.2 所示。

121

图 7.2

3.在 Applet 上输出不同类型的数据变量

(1)程序功能:在 Applet 上设置不同背景色、前景色,并使用不同字体、颜色显示不同类型的

数据变量。

(2)编写 LX7_3.java 程序文件,源代码如下。

import java.applet.Applet;

import java.awt.*;

import java.awt.Color;

public class LX7_3 extends Applet {

String s="这是字符串类数据变量 This is a string";

char c[]={'这','是','一','个','字','符','数','组'};

byte b[]={97,' ','b','y','t','e',' ',97,114,114,97,121};

public void init() {

Color col=new Color(20,55,75);

setBackground(col);//设置 Applet 的背景色

setForeground(Color.yellow);//设置 Applet 的前景色

//repaint();

}

public void paint(Graphics g) {

g.setFont(new Font("黑体",Font.PLAIN,20));//正常的

g.drawString(s,30,30);//写出字符串

122

g.setFont(new Font("宋体",Font.BOLD,20));//加粗的

g.setColor(Color.red);//设置青色

g.drawChars(c,0,8,30,60);//写出字符变量

g.setFont(new Font("SansSerif",Font.ITALIC,24));//倾斜的

g.drawBytes(b,0,12,30,90);//写出字节变量

}

}

(3)编译程序 LX7_3.java。

(4)编写显示 LX7_3.class 的页面文件,在浏览器中显示结果如图 7.3 所示。

图 7.3

练习:在窗口界面中画出图形、写出数据变量。

(二) 插入图像与播放音乐

1. 在 Applet 中插入图像播放音乐

(1)程序功能:在 Applet 中插入 3 种大小的图像,并在打开文件时部分背景音乐。

(2)编写 LX7_4.java 程序文件,源代码如下。

import java.awt.*;

import java.applet.*;

public class LX7_4 extends Applet {

Image img;

public void init(){

img=getImage(getCodeBase(),"image/飞机.gif");//获取图像文件地址读取图

123

像文件到内存

play(getDocumentBase(),"WAV/Sound.wav"); //播放声音文件

}

public void paint(Graphics g){

int w=img.getWidth(this);

int h=img.getHeight(this);

g.drawImage(img,20,10,this); // 画出原图

g.drawImage(img,20,100, w/2, h/2, this); // 画出缩小一倍的图

g.drawImage(img,160,0, w*2, h*2, this); // 画出放大一倍的图

}

}

(3)编译程序 LX7_4.java。

(4)编写显示 LX7_4.class 的页面文件,在浏览器中显示结果如图 7.4 所示。

图 7.4

2.随时播放声音文件的程序

(1)程序功能:在 Applet 中使用下拉框显示音乐文件的名字,在程序中使用 AudioClip 类

控制播放的音乐文件,使用“播放”、“连续”、“停止”按钮控制和选择播放音乐的状态。

(2)编写 LX7_5.java 程序文件,源代码如下。

import java.awt.*;

import java.awt.event.*;

import java.applet.Applet;

124

import java.applet.AudioClip;

public class LX7_5 extends Applet implements ItemListener, ActionListener {

AudioClip sound;

Choice c=new Choice();

Button play=new Button("播放");

Button loop=new Button("连续");

Button stop=new Button("停止");

public void init() {

c.add("space.au"); c.add("flute.aif"); c.add("trip.mid");

c.add("jungle.rmf"); c.add("Sound.wav");

add(c); c.addItemListener(this);

add(play); add(loop); add(stop);

play.addActionListener(this);

loop.addActionListener(this);

stop.addActionListener(this);

sound=getAudioClip(getCodeBase(), "WAV/Sound.wav");

}

public void itemStateChanged(ItemEvent e) {

sound.stop();

sound=getAudioClip(getCodeBase(), "WAV/"+c.getSelectedItem());

}

public void actionPerformed(ActionEvent e) {

if (e.getSource()==play) sound.play();

else if (e.getSource()==loop) sound.loop();

else if (e.getSource()==stop) sound.stop();

}

}

(3)编译程序 LX7_5.java。

(4)编写显示 LX7_5.class 的页面文件,在浏览器中显示结果如图 7.5 所示。

125

图 7.5

(三) 多线程与动画

程序(program)是对数据描述与操作的代码的集合,是应用程序执行的脚本。进程(process)

是程序的一次执行过程,是操作系统运行程序的基本单位。程序是静态的,进程是动态的。系统运

行一个程序就是一个进程从创建、运行到消亡的过程。

线程是比进程更小的运行单位,是程序中单个顺序的流控制。一个进程中可以包含多个线程。

线程是一种特殊的多任务方式。当一个程序执行多线程时,可以运行两个或更多的由同一个程

序启动的任务。这样,一个程序可以使得多个活动任务同时发生。

动画是指连续而平滑地显示多幅图像。计算机动画原理十分简单,首先在屏幕上显示出第一帧

画面,过一会儿把它擦掉,然后再显示下一帧画面,如此循环往复。由于人的眼睛存在着一个视觉

差,所以感觉好像画面中的物体在不断运动。在计算机上,只要以 10~30 幅/每秒钟的速度显示图

像即可达到满意的动画质量。

1.一个简单的动画程序

(1)程序功能:在 Applet 中添加一个“天空”背景图像,然后令一个“飞机”图像从右移

动到左。

(2)编写 LX7_6.java 程序文件,源代码如下。

import java.awt.*;

import java.applet.*;

public class LX7_6 extends Applet {

Image star, rocket;

int x=0;

126

public void init() {

star=getImage(getCodeBase(),"image/天空.JPG");

rocket=getImage(getCodeBase(),"image/飞机.gif");

}

public void paint(Graphics g) {

g.drawImage(star,0,0,this);

g.drawImage(rocket,310-x,10,this);

try {

Thread.sleep(50);

x+=5;

if (x==310) {

x=0;

Thread.sleep(1000);

}

} catch (InterruptedException e) {}

repaint();

}

}

(3)编译程序 LX7_6.java。

(4)编写显示 LX7_6.class 的页面文件,在浏览器中显示结果如图 7.6 所示。

图 7.6

127

(5)程序分析:程序中创建了两个 Image 对象 t1 和 t2,在 init 方法中分别加载了两个图像文

件。使用变量 x 用来改变“飞机”图像画出的位置(310-x,10),因为 x的值是不断变化的,所以看起

来图像在移动。

真正使“飞机”图像实现动画效果的代码在 try…catch 块中。程序调用了 Thread 类的 sleep 方

法(因为 Thread 类属于 Java.lang 包的类,其 sleep 静态类方法可直接调用),因为 sleep 方法会产

生中断异常,所以必须放在 try…catch 块中。如果不使用 sleep 方法,程序将全速运行,必将导致换

帧速度太快,画面闪烁严重(你可以自己去掉 sleep 方法试一试)。休眠时间设定为 50 毫秒,相当于

换帧速度每秒 20(1000/50)。休眠结束后 x 的值加 5,意味着下一帧跳伞画面的显示位置向左移动 5

个像素点。当跳伞移动到 右边即 310 点位置时,将 x 赋值 0,跳伞重新回到了起点。

程序中 paint 方法的 后一条语句是调用 repaint()方法,repaint 方法的功能是重画图像,它先

调用 update 方法将显示区清空,再调用 paint 方法画出图像。它们形成一个循环,paint 调用 repaint,

repaint 调用 paint,使“飞机”图像不间断地反复画出,人看到的是图像在移动。

但运行这个 Applet 时,画面有闪烁现象。一般来说,画面越大,update 以背景色清除显示区所

占用的时间就越长,不可避免地会产生闪烁。如何解决这个问题呢?

2.使用双缓冲创建动画的程序

(1)程序功能:使用双缓冲来建立动画的效果,清除闪烁的现象。

(2)编写 LX7_7.java 程序文件,源代码如下。

import java.awt.*;

import java.applet.*;

public class LX7_7 extends Applet {

Image buffer,img,star;

Graphics g1;

Thread td;

int x=0;

public void init() {

buffer=createImage(getWidth(),getHeight());//创建图像缓冲区

g1=buffer.getGraphics();//创建绘图区

img=getImage(getCodeBase(),"image/飞机.gif");

star=getImage(getCodeBase(),"image/天空.JPG");

}

public void paint(Graphics g) {

g1.drawImage(star,0,0,this); //将图像先画到缓冲区

g1.drawImage(img,310-x,20,this); //将图像先画到缓冲区

128

g.drawImage(buffer,0,0,this);//将缓冲区占的图像画出

try {

Thread.sleep(10);

x+=2;

if (x==310) {

x=2;

Thread.sleep(1000);

}

} catch (InterruptedException e) {}

repaint();

}

public void update(Graphics g) {

paint(g);

}

}

(3)编译程序 LX7_7.java。

(4)编写显示 LX7_7.class 的页面文件,在浏览器中显示结果如图 7.7 所示。

图 7.7

(5)程序说明:

改进后的程序比原程序增加了 Image 类对象 buffer 和 Graphics 类对象 g1。覆盖了 update 方法。

换帧速度提高到 100(1000/10),飞机每次移动 2 个点,动画效果更加平滑而且无闪烁。

新增的 buffer 对象,用作屏幕缓冲区。新增的 g1 对象,用作屏幕绘图区。在 init 方法中,程序

129

调用 Image 对象的 createImage 方法,按照 Applet 的宽度和高度创建了屏幕缓冲区,然后调用

getGraphics 方法创建了 Image 对象 buffer 的绘图区。在 paint 方法中通过 g1.drawImage 改变了图

像输出的方向,图像被画在屏幕缓冲区内。由于屏幕缓冲区不可见,使得画面交替时的闪烁现象也不

可见。当屏幕缓冲区上的画图完成以后,再调用 g.drawImage 方法将整个屏幕缓冲区拷贝到屏幕上,

这个过程是直接覆盖,不会产生闪烁。上述方式被称为图形双缓冲技术。

图形双缓冲技术实际上是创建了一个不可见的后台屏幕,进行幕后操作,图像画在后台屏幕上,

画好之后再拷贝到前台屏幕上。这种技术圆满解决了画面交替时的闪烁,但图像显示速度变慢,内存

占用较大,用户离开网页后,嵌入的 Applet 会继续运行,占用 CPU 时间。

3.使用线程创建动画的程序

(1)程序功能:创建一个显示小球不断跳动并显示不同状态的动画程序。要达到无闪烁现象,显

示速度快,占用内存较小的要求。即要使用双缓冲技术创建图像的显示方式,清除闪烁现象。使用线

程分别解决准备图像、显示图像的任务,解决显示速度慢,占用内存较大的问题。

(2)准备 10 个图像文件(T1.JPG~T10.JPG),它们分别显示小球不同时间的高度和状态,存放

在“程序/image”目录下。这是创建动画的基础工作,是动画显示的内容,应用程序只是解决图像“动”

即显示的方式。

(3)编写 LX7_8.java 程序文件,源代码如下。

(4)编译程序 LX7_8.java。

import java.awt.*;

import java.applet.*;

public class LX7_8 extends Applet implements Runnable {

Image img[]=new Image[10];

Image buffer;

Graphics g1;

Thread td;

int index=0;

public void init() {

buffer=createImage(getWidth(),getHeight());//创建图像缓冲区

g1=buffer.getGraphics();//创建绘图区

for (int i=0;i<10;i++)

img[i]=getImage(getCodeBase(),"image/"+"T"+(i+1)+".JPG");

}

public void start() {

130

if (td==null) {

td=new Thread(this);//创建线程对象

td.start();

}

}

public void stop() {

if (td!=null)

td=null;

}

public void run() {

while(true) {

g1.drawImage(img[index],10,20,this);//画图像到缓冲区

repaint();//画出图像

try {

td.sleep(50);

} catch (InterruptedException e) {}

g1.clearRect(10,20,100,100);//清除缓冲区中的图像

index=++index%10;

}

}

public void paint(Graphics g) {

g.drawImage(buffer,0,0,this);//画出缓冲区中图像

}

public void update(Graphics g) {

paint(g);

}

}

(5)编写显示 LX7_8.class 的页面文件,在浏览器中显示结果如图 7.8 所示。

131

图 7.8

(6)程序说明:

程序中使用图形双缓冲技术,显示一组图像。

程序实现 Runnable 接口中的 run 方法,这是一个和 Applet 同时运行的线程。对线程的控制由

Applet 的 start 和 stop 方法完成,Applet 运行时,就在 start 方法中启动线程,Applet 停止时,就

在 stop 方法中停止线程。

在线程 td 的 run 方法中的永恒循环当中,实现图像的轮流显示使小球不停的跳动。首先调用绘图

对象g1的drawImage方法把当前图像画在屏幕缓冲区内,在paint方法中把屏幕缓冲区拷贝到屏幕上。

但 paint 方法无法直接调用,因为要传递给它一个图形参数 g,故调用 repaint 方法间接调用 paint

方法。repaint 方法无参数,它将调用 update 方法,由 update 方法调用 paint 方法并传递 g 参数。

这就是曾介绍过的一个线程负责准备图像而另一个线程负责显示图像的动画方法。

四、 练习题

1.实验目的:多线程设计、多媒体使用。

2.题意

设计一个交通信号灯类:

(1)变量:位置、颜色(红、黄、绿)、显示时间。

132

(2)方法:切换信号灯。创建并启动两个线程(东西向、南北向)同时运行。

3.实验要求

(1)根据需要设计多个线程。

(2)设计路口信号灯示意图界面。

(3)可将信号灯按方向分为 3 种车道灯:左转、直行和右转。

(4)根据车流量进行时间的模糊控制。

133

实验 8 综合练习

一、 实验目的

将所学知识进行综合运用,模仿设计具有实际意义的应用程序。锻炼使用新类(没有介绍的)类

的能力。

二、 实验要求

1. 在计算机上实现指导书中应用程序。

2. 分析应用程序中使用了哪些系统类,指出使用该类的变量与方法。说明创建了什么类。包含什么

变量与方法。

3. 能根据实际需要使用不同的系统类编写应用程序。

三、 实验内容

(一) 幻灯机效果——连续显示多幅图像

1.程序功能:如果 Applet 仅仅是显示一幅图像,没有什么特别的意义,不如直接在 HTML 文件中

显示图像。本程序可以像幻灯机那样连续显示多幅图像,如图 8.1 所示。

图 8.1

134

2.在当前目录中的 image 文件夹中准备 6 幅花的图像文件。

3.编写 LX8_1.java 程序文件,源代码如下。

import java.awt.*;

import java.awt.event.*;

import java.applet.*;

public class LX8_1 extends Applet {

int index;

Image imgs[]=new Image[6];

public void init(){

addMouseListener(new MouseAdapter() {

public void mouseClicked(MouseEvent e) {

index=++index%6;

repaint();

}

});

for (int i=0; i<6; i++)

imgs[i]=getImage(getCodeBase(),"image/花"+(i+1)+".gif");

}

public void paint(Graphics g){

if (imgs[index]!=null)

g.drawImage(imgs[index],60,20,this);

}

}

在这个程序中,加载了 6 幅图像,点击鼠标可逐一显示图像,并在显示完 6 幅图像后自动返回第

一幅重新开始。

4.对程序进行分析,写出分析结果。

(二) 使用滚动条改变背景颜色

1.程序功能:移动滚动条可以改变背景颜色。运行结果如图 8.2 所示。

135

图 8.2

2.编写 LX8_2.java 程序文件,源代码如下。

import java.applet.Applet;

import java.awt.*;

import java.awt.event.*;

import java.awt.Scrollbar;

import java.awt.Color;

public class LX8_2 extends Applet implements AdjustmentListener {

Scrollbar r1,r2,r3;

int red,green,blue;

TextField t;Label a;

public void init() {

setLayout(null);

r1=new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,255);

r2=new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,255);

r3=new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,255);

t=new TextField("0",5);

t.setEditable(false);

a=new Label("移动滚动条可改变背景颜色",Label.CENTER);

add(a);a.setBounds(120,10,150,15);

add(r1);r1.setBounds(20,30,100,20);

136

add(r2);r2.setBounds(140,30,100,20);

add(r3);r3.setBounds(260,30,100,20);

add(t);t.setBounds(20,120,220,18);

r1.addAdjustmentListener (this);

r2.addAdjustmentListener (this);

r3.addAdjustmentListener (this);

}

public void adjustmentValueChanged(AdjustmentEvent e) {

red=r1.getValue();

green=r2.getValue();

blue=r3.getValue();

t.setText("red 的值"+String.valueOf(r1.getValue())+

",green 的值"+String.valueOf(r2.getValue())+",blue 的值"+

String.valueOf(r3.getValue()));

Color c=new Color(red,green,blue);

setBackground(c);

}

}

3.对程序进行分析,写出分析结果。

(三) Applet 与 Application 合并运行

Java Applet 和 Application 程序的区别在于运行方式不同。那么能不能将它们合并起来,让同

一个程序既可以由浏览器运行又可以单独运行呢?

1.程序功能:在 Applet 与 Application 方式下都能运行。

2.编写 LX8_3.java 程序文件,源代码如下。

import java.applet.*;

import java.awt.*;

import java.awt.event.*;

public class LX8_3 extends Applet implements ActionListener {

Button button;

TextField field;

137

public static void main(String[] args) {

Frame window=new Frame("AppDemo"); // 创建窗口对象

AppDemo app=new AppDemo(); // 创建程序对象

window.add("Center", app); // 将程序对象添加到窗口

app.init(); // 调用程序的初始化方法

window.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

System.exit(0);

}

}); // 以上用匿名类的方式为窗口添加关闭功能,参见第 9 章

window.setSize(300,120); // 设定窗口大小

window.setVisible(true); // 设定窗口可见

}

public void init() {

button=new Button("显示");

button.addActionListener(this);

field=new TextField(23);

add(field);

add(button);

}

public void actionPerformed(ActionEvent e) {

field.setText("Applet 与 Application 的合并运行");

}

}

3.编译 LX8_3.java 源程序。

4.编写浏览 Applet 的页面文件 LX8_3.html,在浏览器打开文件 LX8_3.html,结果如图 8.3(1)

所示。

5.在独立运行的 Application 方式下运行 LX8_3.class 字节文件,结果如图 8.3(2)所示。

138

图 8.3(1)

图 8.3(2)

6.程序分析

从程序结构上看,Applet 必须从 java.applet.Applet 继承,而 Application 必须有一个公共方

法 main。另一方面,两者的主线程也不同,Applet 由 init 方法进行初始化工作,而 Application 由

main 方法启动程序。由于上述差别,编写 Applet 和 Application 合并运行的程序必须遵守一定的规

则。

首先,程序应该是 java.applet.Applet 的子类,这是以 Applet 方式运行的必要条件。如果程序

设计成 Frame 的子类就无法以 Applet 方式运行。其次,需要生成该类的一个实例对象,通过调用对象

的 init 方法进行初始化。

(四) 创建克隆图形

1.程序功能:画出圆的克隆图形。在 Java 中可以实现从现存的对象复制出一个完全一样的副本,

称为克隆。克隆由方法 clone 实现,它是从 Object 继承下来的。圆的克隆图形如图 8.4 所示。

139

图 8.4

2.编写 LX8_4.java 程序文件,源代码如下。

import java.awt.*;

import java.applet.Applet;

public class LX8_4 extends Applet {

public void paint(Graphics g) {

DrawOval c[]=new DrawOval[10];

DrawOval a=new DrawOval();

a.setPos(20,20);

a.setOval(60,60);

for (int i=0; i<10; i++) {

c[i]=(DrawOval)a.clone();

c[i].setPos(20+i*20,20+i*4);

c[i].draw(g);

}

}

}

class DrawOval implements Cloneable {

int x, y, width, height;

public void setPos(int x1, int y1) {

x=x1;

y=y1;

140

}

public void setOval(int w, int h) {

width=w;

height=h;

}

public void draw(Graphics g) {

g.drawOval(x, y, width, height);

}

protected Object clone() {

try {

DrawOval clonedObject=(DrawOval)super.clone();

return clonedObject;

}

catch (CloneNotSupportedException e) {

throw new InternalError();

}

}

}

3.对程序进行分析,写出分析结果。

(五) 创建正弦曲线图形

1.程序功能:在运行程序后,在出现的 Applet 上单击“正弦波形”按钮,可画出一条正弦曲线。

单击“清除”按钮,可清除曲线。

2.编写 LX8_5.java 程序文件,源代码如下。

import java.applet. *; import java.awt.*;

import java.awt.event.*;import java.awt.Color;

public class Sinline extends Applet implements ActionListener{

int x,y;double a;

Button bn1=new Button("正弦波形");

Button bn2=new Button("清除");

public void init(){

add(bn1);add(bn2);

bn1.addActionListener(this);

bn2.addActionListener(this);}

141

public void actionPerformed(ActionEvent e){

Graphics g=getGraphics();

g.drawLine(180,20,180,160);

g.drawLine(0,80,360,80);

g.setColor(Color.red);

if(e.getSource()==bn1){

for(x=0;x<=360;x+=1){

a=Math.sin(x*Math. PI/180);

y=(int)(80+40*a);

g.drawString(".",x,y);}

}

if(e.getSource()==bn2)

repaint();}

}

3.编译源程序。

4.编写浏览 Applet 的页面文件,在浏览器运行结果如图 8.5 所示。

图 8.5

(六) 创建四叶玫瑰线图形

1.程序功能:运行本程序后,选择不同的颜色选项,可画出不同颜色的四叶玫瑰曲线。

2.编写 LX8_6.java 程序文件,源代码如下。

142

import java.awt.*;

import java.applet.Applet;

import java.awt.event.*;

import java.awt.Color;

public class LX8_6 extends Applet implements ItemListener{

Color color = Color.black; //画线的颜色

CheckboxGroup cg1 ;

Checkbox cb1,cb2,cb3;

public void init() {

setBackground(Color.white);

setLayout(new FlowLayout());

cg1 = new CheckboxGroup();

cb1 = new Checkbox("blue",cg1,true);

cb2 = new Checkbox("red",cg1,false);

cb3 = new Checkbox("green",cg1,false);

cb1.addItemListener(this);

cb2.addItemListener(this);

cb3.addItemListener(this);

add(cb1);

add(cb2);

add(cb3); }

public void paint(Graphics g) {

int x0,y0,w1,h1; //原点坐标

w1=600;h1=300;

x0 = w1/2;

y0 = h1/2;

g.setColor(color);

g.drawLine(x0,10,x0,h1);

g.drawLine(0,y0,w1,y0);

int i,j=40,x,y;

double pi=3.14,angle,r;

while (j<200) {

for (i=0;i<1023;i++) {

angle = i*pi/512;

143

r = j*Math.sin(2*angle);

x =(int) Math.round(r*Math.cos(angle)*2);

y =(int) Math.round(r*Math.sin(angle));

g.fillOval(x0+x,y0+y,1,1); } //画圆点

j = j + 20;

}

new Rose1().setVisible(true); }

public void itemStateChanged(ItemEvent e)

{ //选中单选按钮时

if (e.getSource()==cb1) //判断产生事件对象 e 的组件是谁

color = Color.blue;

if (cb2.getState()) //判断单选按钮 cb2 的状态

color = Color.red;

if (cg1.getSelectedCheckbox()==cb3) //判断复选框组 cg1 选中的是谁

color = Color.green;

repaint(); } //重画

}

3.编译源程序。

4.编写浏览 Applet 的页面文件,在浏览器运行结果如图 8.6 所示。

图 8.6

144

(七) 网上购物结算模拟

1.程序功能:创建模拟购物结算界面并实现结算功能。其中使用了内部类和 Vector 向量。运行

程序后,可输入购买记录,单击“添加”按钮将保存记录到 Vector 向量中,并可以显示任意一个记录,

或按记录号删除记录,并可给出购买物品总额,并可清空所有记录。

2.编写 LX8_7.java 程序文件,源代码如下。

import java.util.*;

import java.applet.*;

import java.awt.*;

import java.awt.event.*;

public class LX8_7 extends Applet implements ActionListener {

Vector vect=new Vector();

Label label1,label2,label0;

TextField t0,t1,t2,t3;

TextArea area;

Button btn1, btn2, btn3, btn4, btn5, btn6,btn7,btn8,btn9;

public void init() {

vect=new Vector(1,1);

label0=new Label("品名");label1=new Label("数量");

label2=new Label("单价");

t0=new TextField(10);t1=new TextField(10);t2=new TextField(10);

t3=new TextField(4);

area=new TextArea(10,50);

btn1=new Button("添加"); btn2=new Button("删除");

btn3=new Button("定位"); btn4=new Button("清空");

btn5=new Button("付款"); btn6=new Button("清单");

btn7=new Button("清屏"); btn8=new Button("首位");

btn9=new Button("末位");

add(label0);add(t0);add(label1);add(t1); add(label2);add(t2);

add(btn1);add(btn2);add(btn3);add(t3);add(btn4);add(btn5);

add(btn6);add(btn7);add(btn8);add(btn9);add(area);

145

btn1.addActionListener(this);btn2.addActionListener(this);

btn3.addActionListener(this);btn4.addActionListener(this);

btn5.addActionListener(this);btn6.addActionListener(this);

btn7.addActionListener(this);btn8.addActionListener(this);

btn9.addActionListener(this);

}

public void actionPerformed (ActionEvent e) {

list v=new list(t0.getText(),t1.getText(),t2.getText());

String s0=t0.getText()+t1.getText()+"斤,单价"+t2.getText()+"元";

if (e.getSource()==btn1) {

vect.addElement(v);

int k1=vect.indexOf(v);

area.append("添加"+k1+"记录:"+s0+"\n");

t3.setText(String.valueOf(k1));

}

else if (e.getSource()==btn2) {

int k1=Integer.parseInt(t3.getText());

vect.removeElementAt(k1);

area.append("\n"+"删除了记录:"+s0+"\n");

}

else if (e.getSource()==btn3) {

int k=Integer.parseInt(t3.getText());

list l1=(list)vect.elementAt(k);

t0.setText(l1.pm);

t1.setText(l1.number);

t2.setText(l1.dj);

}

else if (e.getSource()==btn4) {

vect.clear();

area.append("清除所有记录:"+vect.size()+"\n");

}

else if (e.getSource()==btn5) {

area.append("你购买了"+vect.size()+"种物品");

146

double s=0;

for (int i=0;i<vect.size();i++){

list r=(list)vect.elementAt(i);

s=s+Integer.parseInt(r.number)*Double.parseDouble(r.dj);}

area.append("总金额为:"+s+"元,请付款,谢谢。"+"\n");

}

else if (e.getSource()==btn6) {

area.append("\n"+"你购买了"+vect.size()+"种物品,如下所示:"+"\n");

String t="";

for (int i=0;i<vect.size();i++){

list b=(list)vect.elementAt(i);

area.append(t=i+"记录"+b.pm+b.number+"斤,单价"+b.dj+"元"+"\n");}

}

else if (e.getSource()==btn7) {

area.setText(" ");

}

else if (e.getSource()==btn8) {

list v0=(list)vect.elementAt(0);

t0.setText(v0.pm);

t1.setText(v0.number);

t2.setText(v0.dj);t3.setText("0");

}

else if (e.getSource()==btn9) {

list v2=(list)vect.elementAt(vect.size()-1);

t0.setText(v2.pm);

t1.setText(v2.number);

t2.setText(v2.dj);

t3.setText(String.valueOf(vect.size()-1)); }

}

class list { //创建内部类,接受输入内容

String pm,number,dj;

list(String pm,String number,String dj){

this.number = number;

this.pm =pm;

this.dj=dj;}

list(){ this("","",""); }

147

}

}

3.编译源程序。

4.编写浏览 Applet 的页面文件,在浏览器运行结果如图 8.7 所示。

图 8.7

(八) 创建数字和图形时钟

1. 程序功能:创建一个显示当前时间的数字和图形的时钟。

2. 编写 LX8_8.java 程序文件,源代码如下。

import java.awt.Color;

import java.util.*;

import java.awt.*;

import java.applet.*;

public class LX8_8 extends Applet implements Runnable {

Thread timer = null;

Label a;

int lastxs=50, lastys=30, lastxm=50, lastym=30, lastxh=50, lastyh=30;

148

public void init(){ //初始化方法

setBackground(Color.white); //设置 Applet 背景

a=new Label(" ");

add(a);}

public void paint(Graphics g) { //显示数字和图形时钟的方

int xh, yh, xm, ym, xs, ys, s, m, h, xcenter, ycenter;

Date rightnow = new Date(); //获取当前日期和时间

String today = rightnow.toLocaleString(); //时间对应的字符串

a.setText(today); //显示数字时钟

s = rightnow.getSeconds();

m = rightnow.getMinutes();

h = rightnow.getHours();

xcenter=100; ycenter=80; //图形钟的原点

//以下计算秒针、分针、时针位置

xs = (int)(Math.cos(s * 3.14f/30 - 3.14f/2) * 45 + xcenter);

ys = (int)(Math.sin(s * 3.14f/30 - 3.14f/2) * 45 + ycenter);

xm = (int)(Math.cos(m * 3.14f/30 - 3.14f/2) * 40 + xcenter);

ym = (int)(Math.sin(m * 3.14f/30 - 3.14f/2) * 40 + ycenter);

xh = (int)(Math.cos((h*30+m/2)*3.14f/180-3.14f/2)*30+xcenter);

yh = (int)(Math.sin((h*30+m/2)*3.14f/180-3.14f/2)*30+ycenter);

g.setFont(new Font("TimesRoman", Font.PLAIN, 14));

g.setColor(Color.orange); //设置表盘颜色

g.fill3DRect(xcenter-50,ycenter-50,100,100,true); //画表盘

g.setColor(Color.darkGray); //设置表盘数字颜色

g.drawString("9",xcenter-45,ycenter+3); //画表盘上的数字

g.drawString("3",xcenter+40,ycenter+3);

g.drawString("12",xcenter-5,ycenter-37);

g.drawString("6",xcenter-3,ycenter+45);

//时间变化时,需要重新画各个指针,即先消除原有指针,然后画新指针

g.setColor(Color.orange); //用表的填充色画线,可以消除原来画的线

if (xs != lastxs || ys != lastys){ //秒针变化

g.drawLine(xcenter, ycenter, lastxs, lastys); }

if (xm != lastxm || ym != lastym) { //分针变化

g.drawLine(xcenter, ycenter-1, lastxm, lastym);

149

g.drawLine(xcenter-1, ycenter, lastxm, lastym); }

if (xh != lastxh || yh != lastyh) { //时针变化

g.drawLine(xcenter, ycenter-1, lastxh, lastyh);

g.drawLine(xcenter-1, ycenter, lastxh, lastyh); }

g.setColor(Color.red); //使用红色画新指针

g.drawLine(xcenter, ycenter, xs, ys);

g.drawLine(xcenter, ycenter-1, xm, ym);

g.drawLine(xcenter-1, ycenter, xm, ym);

g.drawLine(xcenter, ycenter-1, xh, yh);

g.drawLine(xcenter-1, ycenter, xh, yh);

lastxs=xs; lastys=ys; //保存指针位置

lastxm=xm; lastym=ym;

lastxh=xh; lastyh=yh; }

public void start() { //启动线程的方法

if(timer == null) {

timer = new Thread(this);

timer.start(); }}

public void stop(){ //停止线程方法

timer = null; }

public void run(){ //每隔一秒钟,刷新一次画面的方法

while (timer != null) {

try { Thread.sleep(1000); }

catch (InterruptedException e) {}

repaint();} //调用 paint()方法重画时钟

timer = null; }

public void update(Graphics g) { //重写该方法是为了消除抖动现象

paint(g); }

}

3. 编译源程序。

4. 编写浏览 Applet 的页面文件,在浏览器运行结果如图 8.8 所示。

150

图 8.10

(九) 在 Applet 的画布上随意画图

1. 程序功能:在 Applet 上使用鼠标在屏幕上随意画直线和画点。用户点击“画线”按钮可

画直线,点击“画点”按钮可画连续点,点击“清除”按钮可清除画面上的所有内容。。

2. 编写 LX8_9.java 程序文件,源代码如下。

import java.applet.Applet;

import java.awt.*;

import java.awt.event.*;

import java.util.Vector;

import java.awt.Rectangle;

import java.awt.Color;

public class LX8_9 extends Applet implements ActionListener {

Button line, point, clear;

MyCanvas2 c;

public void init() {

c=new MyCanvas2();

c.setSize(350,200);

c.setBackground(Color.green);

line=new Button("画线");

151

point=new Button("画点");

clear=new Button("清除");

add(line);

add(point);

add(clear);

add(c);

line.addActionListener(this);

point.addActionListener(this);

clear.addActionListener(this);

}

public void actionPerformed(ActionEvent e) {

if (e.getSource()==line) // 设为画直线模式

c.mode=0;

else if (e.getSource()==point) // 设为画连续点模式

c.mode=1;

else if (e.getSource()==clear) { // 清除画面

c.points=new Vector();

c.x1= -1;

c.repaint();

}

}

}

class MyCanvas2 extends Canvas implements

MouseListener,MouseMotionListener {

int x1, y1, x2, y2, mode;

Vector points=new Vector();

MyCanvas2() {

addMouseListener(this);

addMouseMotionListener(this);

}

public void paint(Graphics g) {

for (int i=0;i<points.size();i++) { // 所有操作结果被重新画出

152

Rectangle r=(Rectangle)points.elementAt(i);

g.drawLine(r.x, r.y, r.width, r.height);

}

if (x1!= -1 && mode ==0) //画当前直线

g.drawLine(x1, y1, x2, y2);

}

public void mousePressed(MouseEvent e) { // 记录起点坐标

x1=e.getX();

y1=e.getY();

}

public void mouseDragged(MouseEvent e) {

if (mode==0) { // 记录当前坐标

x2=e.getX();

y2=e.getY();

}

else { // 画连续点时保存每一个笔画的起点和当前坐标

points.addElement(new Rectangle(x1, y1, e.getX(), e.getY()));

x1=e.getX();

y1=e.getY();

}

repaint();

}

public void mouseReleased(MouseEvent e) {

if (mode==0) // 保存当前直线的起点和终点坐标

points.addElement(new Rectangle(x1, y1, e.getX(), e.getY()));

}

public void mouseClicked(MouseEvent e) {}

public void mouseEntered(MouseEvent e) {}

public void mouseExited(MouseEvent e) {}

public void mouseMoved(MouseEvent e) {}

}

3. 编译源程序。

153

4. 编写浏览 Applet 的页面文件,在浏览器运行结果如图 8.9 所示。本页面显示的是通过鼠

标使用直线画出的旗子,再用画点的方法画出的字。

图 8.9

5.分析程序,写出分析结果。

(十) 创建电闪雷鸣的动画

1.程序功能:本程序可以通过按钮控制声音和动画的开始和停止操作。动画显示了电闪雷鸣的场

面。注意:图像文件要分别表现不同时间段的电闪场面,这样才会有动画效果。

2.编写 LX8_10.java 程序文件,源代码如下。

import java.awt.*;

import java.applet.*;

import java.awt.event.*;

public class LX8_10 extends Applet implements Runnable,ActionListener

{

Image iImages[]; //图像数组

Thread aThread;

int iFrame; //图像数组下标

154

AudioClip au; //定义一个声音对象

Button b1,b2;

public void init()

{

int i,j;

iFrame=0;

aThread=null;

iImages = new Image[10];

for (i=0;i<10;i++)

{

iImages[i] =getImage(getCodeBase(),"image/"+"tu"+(i+1)+".JPG");

}

au=getAudioClip(getDocumentBase(),"Wav/Sound.wav");

au.play(); //播放一次声音文件

Panel p1 = new Panel();

b1 = new Button("开始");

b2 = new Button("停止");

p1.add(b1);

p1.add(b2);

b1.addActionListener(this);

b2.addActionListener(this);

setLayout(new BorderLayout());

add(p1,"South");

}

public void start()

{

if (aThread == null)

{

aThread = new Thread(this);

aThread.start(); //线程启动

b1.setEnabled(false);

}

}

public void stop()

{

155

if (aThread != null)

{

aThread.interrupt(); //线程中断

aThread = null;

au.stop(); //停止播放声音文件

}

}

public void run()

{

while (true)

{

iFrame++;

iFrame %= (iImages.length); //下一幅图像的下标

repaint();

try

{

Thread.sleep(50);

}

catch (InterruptedException e)

{ //中断时抛出

break; //退出循环

}

}

}

public void update(Graphics g)

{

g.drawImage(iImages[iFrame],0,0,this);

}

public void actionPerformed(ActionEvent e)

{

if ((e.getSource()==b1) && (aThread == null) )

{ //单击 Start 按钮时触发

aThread = new Thread(this);

aThread.start(); //线程启动

b1.setEnabled(false);

156

b2.setEnabled(true);

au.loop(); //循环播放声音文件

}

if ((e.getSource()==b2) && (aThread != null) )

{ //单击 Stop 按钮时触发

aThread.interrupt(); //线程中断

aThread = null;

b1.setEnabled(true);

b2.setEnabled(false);

au.stop(); //停止播放声音文件

}

}

}

3.编译源程序。

4.编写浏览 Applet 的页面文件,在浏览器运行结果如图 8.10 所示。

图 8.10

157

(十一) 动画显示文字

1.程序功能:在 Applet 页面上显示一个由小连续变大的字符串"这是文字动画"。

2.编写 LX8_11.java 程序文件,源代码如下。

import java.awt.*;

import java.applet.*;

import java.awt.Color;

public class LX8_11 extends Applet implements Runnable {

Image buffer;

Graphics gContext;

Thread animate;

String s="这是文字动画";

int w, h, x, y, size=12;

public void init() {

w=getWidth();

h=getHeight();

buffer=createImage(w,h);

gContext=buffer.getGraphics();

gContext.setColor(Color.blue);

}

public void start() {

if (animate==null){

animate=new Thread(this);

animate.start();

}

}

public void stop() {

if (animate!=null)

animate=null;

}

public void run() {

158

while(true) {

x=(w-s.length()*size)/2; y=(h+size)/2;

gContext.setFont(new Font("宋体",Font.PLAIN,size));

gContext.drawString(s,x,y);

repaint();

try {

animate.sleep(50);

} catch (InterruptedException e) {}

gContext.clearRect(0,0,w,h);

if (++size>40)

size=12;

}

}

public void paint(Graphics g) {

g.drawImage(buffer,0,0,this);

}

public void update(Graphics g) {

paint(g);

}

}

3.编译源程序。

4.编写浏览 Applet 的页面文件,在浏览器运行结果如图 8.11 所示。

图 8.11

159

(十二) 移动文字的控制

1.程序功能:通过“启动”和“中断”按钮控制文字移动。其界面如图 8.12 所示。

图 8.12

2.编写 LX8_12.java 程序文件,源代码如下。

import java.awt.*;

import java.awt.event.*;import java.applet.*;

public class LX8_12 extends Applet implements ActionListener

{

static LX8_12.Td wt1,wt2;

public void init()

{

wt1=new Td("你好!");

wt2=new Td("我在移动!");

wt2.start();

wt2.setButton(); //设置按钮状态

setLayout(new GridLayout(4,1));

}

public class Td extends Thread

160

{

Panel p1;

Label lb1; TextField tf1,tf2; Button b1,b2;

int sleeptime = (int)(Math.random()*100);

public Td(String str)

{

super(str);

for(int i=0;i<100;i++)

str = str + " ";

tf1 = new TextField(str); add(tf1);

p1 = new Panel();

p1.setLayout(new FlowLayout(FlowLayout.LEFT));

lb1 = new Label("sleep");

tf2 = new TextField(""+sleeptime);

p1.add(lb1); p1.add(tf2);

b1 = new Button("启动"); b2 = new Button("中断");

p1.add(b1); p1.add(b2);

b1.addActionListener(new LX8_12());

b2.addActionListener(new LX8_12());

add(p1);

}

public void run()

{

String str;

while (this.isAlive() && !this.isInterrupted())

{ //线程活动且没中断时

try

{

str = tf1.getText();

str = str.substring(1)+ str.substring(0,1);

tf1.setText(str);

this.sleep(sleeptime);

}

catch(InterruptedException e)

{ //中断时抛出

161

System.out.println(e);

break; //退出循环

}

}

}

public void setButton() //设置按钮状态

{

if (this.isAlive())

b1.setEnabled(false);

if (this.isInterrupted())

b2.setEnabled(false);

}

}

public void actionPerformed(ActionEvent e)

{ //单击按钮时触发

if ((e.getSource()==wt1.b1) || (e.getSource()==wt1.b2))

actionPerformed(e,wt1);

if ((e.getSource()==wt2.b1) || (e.getSource()==wt2.b2))

actionPerformed(e,wt2);

}

public void actionPerformed(ActionEvent e,Td wt1)

{ //重载

if(e.getSource()==wt1.b1) //启动

{

wt1.sleeptime=Integer.parseInt(wt1.tf2.getText());

wt1.start();

}

if(e.getSource()==wt1.b2) //中断

wt1.interrupt();

wt1.setButton(); //设置按钮状态

}

}

3.编译源程序。

4.编写浏览 Applet 的页面文件,在浏览器运行程序。

5.分析程序结构,写出分析结果。

162

(十三) 创建图像的水中倒影

1.程序功能:Applet 的页面上显示一幅图像制作出它的水中倒影,并能显示动态的水波纹。

2.LX8_13.java 程序文件,源代码如下。

import java.awt.*;

import java.applet.*;

public class LX8_13 extends Applet implements Runnable {

Thread animate;

Image img,buffer;

Graphics gContext;

int width,height;

public void init() {

img=getImage(getCodeBase(),"image/山.JPG");

MediaTracker tracker=new MediaTracker(this); // 创建图像加载跟踪器

tracker.addImage(img,0); // 添加要跟踪的图像,代号为 0

try {

tracker.waitForID(0); // 等待图像加载完毕

} catch (InterruptedException e) {}

width=img.getWidth(this);

height=img.getHeight(this)/2; // 仅使用图像的一半

buffer=createImage(2*width,height); // 创建后台屏幕,原始图像的两倍宽度

gContext=buffer.getGraphics();

gContext.drawImage(img,0,-height,this); // 图像的下半部分画到后台屏幕

for (int i=0;i<height;i++) // 将图像逐线拷贝,生成图像倒影

gContext.copyArea(0,i,width,1,width,(height-1)-2*i); // 拷贝到后台屏幕右

半边

gContext.clearRect(0,0,width,height); // 清除后台屏幕左半边

}

public void start() {

163

if (animate==null) {

animate=new Thread(this);

animate.start();

}

}

public void stop() {

if (animate!=null)

animate=null;

}

public void run() {

int dy,num=0;

double d;

while (true) {

d=num*Math.PI/6; // 生成一个角度,共有 12 个值

for (int i=0;i<height;i++) {

dy=(int)((i/12.0D+1)*Math.sin(height/12.0D*(height-i)/(i+1)+d)); // 经

验公式

gContext.copyArea(width,i+dy,width,1,-width,-dy); // 从右向左拷贝生成波

}

repaint();

num=++num%12;

try {

Thread.sleep(50);

} catch (InterruptedException e) {}

}

}

public void update(Graphics g) {

paint(g);

}

public void paint(Graphics g) {

164

g.drawImage(img,0,-height,this); // 显示图像的下半部分

g.drawImage(buffer,0,height,this); // 显示图像倒影,合成一幅完整图像

}

}

3.编译源程序。

4.编写浏览 Applet 的页面文件,在浏览器运行结果如图 8.13 所示。

图 8.13

5.分析程序结果,写出分析结果。

(十四) 建立到其它网站的接口

1.程序功能:在 Applet 页面上,点击按钮打开 Java 和 Yahoo 网站的首页。该程序使用了 URL

类。

2.编写 LX8_14.java 程序文件,源代码如下。

import java.awt.*;

165

import java.awt.event.*;

import java.net.*;

import java.applet.Applet;

class HomeButton extends Button {

String name;

URL home;

HomeButton(String name, String site) {

setLabel(name);

try {

home=new URL(site);

}

catch (MalformedURLException e) {}

}

}

public class LX8_14 extends Applet implements ActionListener {

HomeButton javaHome=new HomeButton("Java", "http://java.sun.com");

HomeButton yahooHome=new HomeButton("Yahoo", "http://www.yahoo.com");

public void init() {

add(javaHome);

add(yahooHome);

javaHome.addActionListener(this);

yahooHome.addActionListener(this);

}

public void actionPerformed(ActionEvent e) {

HomeButton btn=(HomeButton)e.getSource();

getAppletContext().showDocument(btn.home);

}

}

3.编译源程序。

4.编写浏览 Applet 的页面文件,在浏览器运行结果如图 8.14 所示。

166

图 8.14

5.了解 URL 类的变量与方法。

(十五) 建立输入保存信息的窗口

1.程序功能:本程序创建了一个输入信息保存信息的窗口界面,在窗口中可以打开一个文本文件

并将文件信息显示到界面中。还可以将输入的信息,存到文件中。

2.LX8_15.java 程序文件,源代码如下。

import java.awt.Color;

import java.awt.*;import java.awt.List;

import java.util.*;

import java.awt.event.*;import java.io.*;

public class LX8_15 extends WindowAdapter

implements ActionListener,ItemListener

{

Frame f; Vector vect=new Vector();

Label label1=new Label("输入编号"); Label label2=new Label("输入姓名");

TextField tf1,tf2;TextArea area;

Checkbox cb1,cb2; Choice c1,c2;

List ls1; Button b1,b2,b3,b4;

public static void main(String arg[]){

(new LX8_15()).init();

}

public void init(){

Panel p1,p2;

CheckboxGroup cg;

f = new Frame("输入学生基本信息窗口");

167

f.setSize(480,200);

f.setLocation(200,140);

f.setBackground(Color.lightGray);

f.setLayout(new GridLayout(1,2)); //网格布局,左右分隔窗口

ls1 = new List(); //创建列表框

f.add(ls1); //占据窗口左半部分

p1 = new Panel();

p1.setLayout(new GridLayout(6,2)); //网格布局,6 行 1 列

f.add(p1); //占据窗口右半部分

tf1 = new TextField ("1"); //创建组件

tf2 = new TextField ("Name");

cg = new CheckboxGroup(); //创建复选框组

cb1 = new Checkbox("男",cg,true); //创建单选按钮

cb2 = new Checkbox("女",cg,false);

c1 = new Choice(); //创建选择框

c1.addItem("经济管理学院"); //添加选择框的选项

c1.addItem("理学院");

c1.addItemListener(this); //注册选择框事件监听程序

c2 = new Choice(); //创建选择框

c2.addItem("信息系");

b1 = new Button("添加"); b2 = new Button("保存");

b3 = new Button("打开文件");b4 = new Button("清屏");

b1.addActionListener(this);b2.addActionListener(this);

b3.addActionListener(this);b4.addActionListener(this);

p1.add(label1);p1.add(label2);

p1.add(tf1);p1.add(tf2); //组件依次添加到面板 p1 上

p1.add(cb1); p1.add(cb2);p1.add(c1); p1.add(c2);

p1.add(b1);p1.add(b2);p1.add(b3);p1.add(b4);

f.addWindowListener(this);f.setVisible(true);

b1.setEnabled(false);b2.setEnabled(false);

}

public void windowClosing(WindowEvent e)

{

System.exit(0);

}

public void actionPerformed(ActionEvent e){

168

String str=new String("");

if (e.getSource()==b1){ //单击“添加”按钮时,显示添加内容,暂时保存到向

量中

if (cb1.getState())

str =cb1.getLabel();

if (cb2.getState())

str = cb2.getLabel();

str=tf1.getText()+" "+tf2.getText()+" "+str+"

"+c1.getSelectedItem()+" "+c2.getSelectedItem();

ls1.add(str);

vect.addElement(str);

tf1.setText(""+(Integer.parseInt(tf1.getText())+1));

}

if (e.getSource()==b2) { //单击保存按钮时将添加内容保存到文件中

try{

FileOutputStream fout = new FileOutputStream("student.txt",true);

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fout));

for (int i=0;i<vect.size();i++){

String xx1=vect.elementAt(i).toString();

out.write(xx1+"\n"); //写入对象

}

out.close();vect.clear();

}

catch (FileNotFoundException fe){}

catch (IOException ioe){}

}

if (e.getSource()==b4) {

ls1.removeAll();

}

if (e.getSource()==b3) { //单击打开按钮打开文件显示文件内容

try {

FileInputStream fin = new FileInputStream("student.txt");

BufferedReader in = new BufferedReader(new InputStreamReader(fin));

for (int i=0;;) {

String xx=in.readLine();//读出内容

if(xx==null)

169

break;

ls1.add(xx);

vect.addElement(xx);

}

b1.setEnabled(true);b2.setEnabled(true);

in.close(); vect.clear();

}

catch (FileNotFoundException fe){}

catch (IOException ioe){}

}

}

public void itemStateChanged(ItemEvent e){

if (c1.getSelectedIndex()==0){ //对选择框 c1 操作时触发

c2.removeAll(); //清除选择框 c2 全部内容

c2.addItem("信息系"); //选择框 c2 添加内容

c2.addItem("经济系");

c2.addItem("会计系");

}

if (c1.getSelectedIndex()==1){

c2.removeAll();

c2.addItem("数学系");c2.addItem("物理系");c2.addItem("模型系");

}

}

}

3.编译并运行程序,其界面窗口如图 8.15 所示。

图 8.15

170

(十六) 简单的文本编辑器

1.程序功能:创建一个简单的文本编辑器,可打开文件对话框选择打开一个文件,并在文本区进

行编辑,然后把它保存起来。

2.编写 LX8_16.java 程序文件,源代码如下。

import java.io.*;

import java.awt.*;

import java.awt.event.*;

public class LX8_16 extends Frame implements ActionListener {

FileDialog fileDlg;

String str, fileName;

byte byteBuf[]=new byte[10000];

TextArea ta=new TextArea();

MenuBar mb=new MenuBar();

Menu m1=new Menu("文件");

MenuItem open=new MenuItem("打开");

MenuItem close=new MenuItem("关闭");

MenuItem save=new MenuItem("保存");

MenuItem exit=new MenuItem("退出");

LX8_16() {

setTitle("简易文本编辑器");

setSize(400,280);

add("Center", ta);

addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

System.exit(0);

}

} );

m1.add(open);

m1.add(close);

m1.add(save);

m1.addSeparator();

171

m1.add(exit);

open.addActionListener(this);

close.addActionListener(this);

save.addActionListener(this);

exit.addActionListener(this);

mb.add(m1);

setMenuBar(mb);

show();

}

public void actionPerformed(ActionEvent e) {

if (e.getSource()==exit)

System.exit(0);

else if (e.getSource()==close) // 关闭文件

ta.setText(null); // 设置文本区为空

else if (e.getSource()==open) { // 打开文件

fileDlg=new FileDialog(this,"打开文件"); // 生成文件对话框

fileDlg.show(); // 显示文件对话框

fileName=fileDlg.getFile(); // 获取文件名

try {

FileInputStream in=new FileInputStream(fileName); // 建立文件输入流

in.read(byteBuf); // 将文件内容读到字节数组

in.close(); // 关闭文件输入流

str=new String(byteBuf); // 将字节数组转换成字符串

ta.setText(str); // 将字符串显示在文字区

setTitle("简易文本编辑器 - "+fileName);

} catch(IOException ioe) {}

}

else if (e.getSource()==save) { // 保存文件

fileDlg=new FileDialog(this,"保存文件",FileDialog.SAVE); // 生成文件对话

fileDlg.show();

fileName=fileDlg.getFile();

str=ta.getText(); // 将文本区内容读至字符串

byteBuf=str.getBytes(); // 将字符串转换成字节数组

172

try {

FileOutputStream out=new FileOutputStream(fileName); // 建立文件输出流

out.write(byteBuf); // 将字节数组写入文件输出流

out.close(); // 关闭文件输出流

} catch(IOException ioe) {}

}

}

public static void main(String args[]) {

new LX8_16();

}

}

3.编译并运行程序,出现如图 8.16(1)所示窗口。

图 8.16(1)

4.单击“文件”下拉菜单中的“打开”菜单项,将弹出文件对话框,如图 8.16(2)所示。

图 8.16(2)

173

5.从中选取要打开的文本文件,则文件的内容会显示在文本编辑区,如图 8.16(3)所示。在文

本区中,可以进行常规的编辑操作。尽管没有添加弹出式菜单,但点击鼠标右键时还会有一个系统的

弹出式编辑菜单出现。

图 8.16(3)

6.选取“文件”中的“保存”菜单项将打开保存文件对话框,如图 8.16(4)所示。可直接输入

文件名,也可从文件显示区选择一个文件名,此时将弹出一个警告对话框,让你确认是否覆盖原文件。

图 8.16(4)

7.分析程序结构,写出分析结果。

174

编程注意事项

一、可读性

一个好的程序要具备可读性,可方便自己也可方便别人。所以,要培养一个良好的编程习惯,可

注意以下几方面:

1. 代码的缩进;

2. 有效使用空格;

3. 简明的注释;

4. 意义明确的命名;

5. 着重表示的常量。

二、亲手编写源程序

在编写 Java 程序过程中,还可以利用一些可视化的开发工具,它们可以综合使用 Java 的编译器

和调试器等,例如 Symantec 公司的 Visual Café、Kawa、Sun 公司的 Java Worshop 和 Java Studio、

Inprise 公司的 JBuilder、微软的 Visual J++等,使用编程开发工具可以加快编程的速度。但在初始

学习时还是 好亲手编写源程序,以便理解类和编程思想。

三、立即运行程序

编写的源程序要立即上机编译运行来检验程序中存在的问题。通过运行的结果验证程序的功能是

否实现。有一些系统类的方法、变量也需要上机实验去了解它们的含义。

Java 还有很多相关的技术,JavaScript 是具有 Java 子集的脚本语言,可用于编写 ASP 文件;JSP

是比 ASP 更优越的 Web 动态开发技术,以 Java 作为脚本语言,通过 JDBC 能够利用 SQL 与数据库进行

通信,使 Java 得到更大范围的应用,如企业信息系统开发,电子商务网站开发。Java 在 2D 图形、3D

动画、移动电话方面也有很好的应用,学习 Java 才是刚刚开始。

175

建议参考书

[1] 叶核亚,陈立. Java 2 程序设计实用教程. 北京:电子工业出版社,2003.5

[2] 张如健,舍三明. Java 程序设计与实用技术速成培训. 北京:电子工业出版社,2000.1

[3] 邵光亚,邵丽萍. Java 语言程序设计. 北京:清华大学出版社,2001.9

[4] 邵丽萍等. Java 语言程序设计实用教程. 北京:清华大学出版社,2004.1