JAVA技术教程(基础篇)
说明:JAVA语言是随着网络的不断发展而产生的一种计算机高级语
言,它具备优越的安全性、可移植性等。阐述过程中,对语言的普遍
意义上的内容将不做重点介绍,如JAVA的数据类型、语法等。另外,
由于JAVA语言是一种面向对象的,对于面向对象的理论讲解也将不
作为重点,而讲述面向对象在JAVA中的实现。对JAVA根据实际的
需要,将重点阐述APPLET技术、线程技术,对于AWT、JAVA高级
网络技术如JSP、JDBC等内容将作为介绍性内容。
第一部分JAVA程序介绍
1、程序类型:
Application应用程序和Applet小应用程序
i.Application应用程序与C++一样,是完全独立开发和应用的
程序(关于JAVA与C及C++的具体区别在后面将做详细介
绍)。
ii.Applet小应用程序是JAVA实现与Internet交互的、能够实现
网络特性的应用程序。其必须嵌入Html中实现程序的运行,
不能独立运行。
2、JAVA程序结构:
JAVA的程序结构包括四部分:原代码.java,类文件.class,
文件归档工具jar生成的.jar和存储对象状态的序列文件.ser
原代码JAVA的文件结构如下:
package(0or1)
import(0orserveral)
//JAVA默认状态为java.lang,object包,所以在简单的程序
过程中可以不用引入包。
publicclassDefinition(0or1)
classDefinition(0orserveral)
interfaceDefinition(0orserveral)
3、程序实例:
Java程序的开发过程:
1.Application:应用程序的开发
•编辑你的程序文件,存为纯文本文件javaApp.java,后
缀必须为java
(可以通过任意的文本编辑工具写入程序代码,后缀名
为java)
例1
classjavaApp
(
publicstaticvoidmain(Stringargs[])
(
System.out.println("这是我的第一个Java
Application!");
)
)
•编译成类class文件:javacjavaApp.java
•执行程序:javajavaApp
•main方法中的参数同样如C及C++中一样能够传递参
数
注意:
用javac和java编译、执行源、类文件的时javac编译必须
带后缀.java;java执行类文件不带.class后缀;文件名大小
写必须一致。且文件名必须Application程序入口类(唯一
含main方法的类)名称一致。如果Java源文件的文件名
不是入口类的名称,编译后产生的类文件依然会是与入口
类名相同的名称。
上述程序中首先用保留字class来声明一个新的类,其类
名为javaApp,它是一个公共类(public)。整个类定义由
大括号{}括起来。在该类中定义了一个main()方法,
其中public表示访问权限,指明所有的类都可以使用这一
方法;static指明该方法是一个类方法,它可以通过类名
直接调用;void则指明main()方法不返回任何值。对于
一个应用程序来说,main()方法是必须的,而且必须按照
如上的格式来定义。Java解释器在没有生成任何实例的情
况下,以main()作为入口来执行程序。Java程序中可以
定义多个类,每个类中可以定义多个方法,但是最多只能
有一个公共类,main()方法也只能有一个,作为程序的入
口。main()方法定义中,括号()中的Stringargs[]是
传递给main()方法的参数,参数名为args,它是类String
的一个实例,参数可以为。个或多个,每个参数用“类名
参数名”来指定,多个参数间用逗号分隔。
现在我们可以运行该程序。首先把它放到一个名为
javaApp.java的文件中,这里,文件名应和类名相同,因
为Java解释器要求公共类必须放在与其同名的文件中。然
后对它进行编译:
C:>编译器路径javacJavaApp.java
编译的结果是生成字节码文件javaApp.classo最后用
java解释器来运行该字节码文件:
C:>javajavaApp
2.Applet:小应用程序的开发
•同上,也需要编译为class文件,源文件javaApplet.java
如下:
例2:
importjava.awt.*;
publicclassjavaAppletextendsjava.applet.Applet
(
publicvoidpaint(Graphicsg)
(
g.drawString("这是我的第一个Java
Applet!",40,20);
)
)
•生成HTML文件first.html,含上面的java类:
<html>
<body>
<center>
<hl>下面的文字是用Java输出的!</hl>
</center>
<appletcode="javaApplet.class"width=400height=300>
</applet>
</body>
</html>
•用浏览器或java的浏览器运行:
appletviewerfirst.html
注意:
a)在Html嵌入的是Java原程序经过编译后生成的
Class文件;
b)Html中applet标记含有很多参数针对如何调用
applet,其中重要的有:code=(applet文件
名),codebase=(代码基址,是包含着applet代码的目
录。在没有给出时,默认为当前html文档的地址)、
<paramname=参数名value=参数值>。
例2这是一个简单的Applet(小应用程序)。程序中,首
先用import语句输入java,awt下所有的包,使得该程
序可能使用这些包中所定义的类,它类似于C中的
#include语句。然后声明一个公共类javaApplet,用
extends指明它是Applet的子类。在类中,我们重写父
类Applet的paint()方法,其中参数g为Graphics类,
它表明当前作画的上下文。在paint()方法中,调用g
的方法drawString(),在坐标处输出字符串““这是我
的第一个JavaApplet!”,其中坐标是用象素点来表示
的。
这个程序中没有实现main()方法,这是Applet与应用
程序Application(如例1)的区别之一。为了运行该
程序,首先我们也要把它放在文件javaApplet.java中,
然后对它进行编译:
C:>javacjavaApplet.java
得到字节码文件javaApplet.class。由于Applet中没
有main()方法作为Java解释器的入口,我们必须编写
HTML文件,把该Applet嵌入其中,然后用appletviewer
来运行,或在支持Java的浏览器上运行。它的文件如
下:
<HTML>
<HEAD>
<TITLE>AnApplet</TITLE>
</HEAD>
<BODY>
<appIetcode="javaAppIet.cIass“width=200
height=40>
</appIet>
</BODY>
</HTML>
其中用〈Applet)标记来启动javaApplet,code指明字
节码所在的文件,width和height指明applet所占的
大小,我们把这个HTML文件存入Example.html,然后
运行:
C:>appletviewerExample,html
从上述例子中可以看出,Java程序是由类构成的,对于
一个应用程序来说,必须有一个类中定义main()方法,
而对applet来说,它必须作为Applet一个子类。在类的
定义中,应包含类变量的声明和类中方法的实现。Java
在基本数据类型、运算符、表达式、控制语句等方面与
C、C++基本上是相同的,但它同时也增加了一些新的
内容,在以后的各章中,会详细介绍。本节中,只是使
大家对Java程序有一个初步的了解。
3、Applet和Application的混合程序:
Java类文件有可能既是一个javaapplication又是java
appleto虽然这样的java文件比较复杂,但是它却既可
以在浏览器中运行,又可以单独运行。
实例:
例3:
importjava.applet.Applet;
importjava.awt.*;
importjava.awt.event.*;
publicclassAppletappextendsApplet{
publicstaticvoidmain(Stringargs[]){
Frameframe=newFrame("Application");
//创建一个Frame对象作为装载Applet的环境
Appletappapp=newAppletappO;
frame.add("center",app);
frame.setSize(200,200);
frame.validate();
frame,addWindowListener(new
WindowControl(app));
app.init();
app.start();
)
publicvoidpaint(Graphicsg){
g.drawString("helloappletapplication",25,25);
)
publicvoiddestroy(){
System.exit(O);
)
)
classWindowControlextendsWindowAdapter{
Appletc;
publicWindowControl(Appletc){
this.c=c;
)
publicvoidwindowClosing(WindowEvente){
c.destroy();
)
)
4、Java程序开发平台的介绍:
开发Java程序一般使用的平台主要有:JDK、Jbuild、VJ++等。
其中主要介绍JDK、Jbuild。
二、面向对象程序设计
关于JAVA中面向对象的程序设计概念,由于在《面向对象程序设计
和C++实践》中,已经进行了详细的解释。所以,在此关于JAVA中
面向对象的知识将重点介绍以下内容,其余部分将在具体程序事例中
讲述。
1、接口:
a)接口产生的意义:由于JAVA只允许单重继承性,即每个Java
中的类只能有一个父类(但一个父类可以有多个子类)。多重
继承增加了编程的复杂性,但提高了编程的功能。Java为了弥
补由于单继承性而带来程序功能降低的缺陷,特别是在我们创
建的类的行为在类层次的不同分支中已有定义的情况,就提出
接口的概念。在某种程度上,接口具有这类的特性。
b)接口的定义:接口就是一种没有完全实现的类,包含抽象的方
法和常量定义。接口中不能有方法实现的具体代码。接口就是
抽象的类。定义接口使用interface关键字。
erfacePrintable{
voidprint();
)
classMouseimplementsPrintable{
voidprint(){
System.out.println("Mouse");
)
)
classDuckimplementsPrintable{
voidprint(){
System.out.println(“Duck");
)
)
c)接口的使用:
i.接口的定义和类相似,在很多地方它们同样进行处理,它
们定义在同一个文件中。不同的是接口不需要通过new来
创建它的实体。
ii.接口也是可以相互继承的。
如:interfaceAextendsB{
iii.一个类同时可以实现多个接口。
如:classclass_AinterfaceA_inteface,B_interface....{
)
iv.在类实现了某个接口后就必须在类中对该接口的抽象方法
具体化即给抽象方法写具体代码。
v.接口可以实现多重继承,既可以通过extends将多个接口组
合成一个接口。但接口不能通过implements实现其它接口。
vi.java类库中也提供了很多接口,Runnable就是其中一个。
(具体可查阅相关资料或开发平台中的帮助,线程的定义
和实现中就是通过某个类实现Runnable接口的)
2、包:
a)包产生的意义:
i.包的使用可以实现一组类和接口的封装,这也正是面向对
象的思想。
ii.由于java编译器以入口类名为文件名生成源文件,这在一
定程度上会造成同名类的冲突,通过java技术基础包可以使在其后定义
的所有类集合在一起,使在不同包中的入口类名相同。
b)包的定义:package关键字定义包。
如:packageFirst_package;
publiclassMyclass{
)
classyourclass{
c)包的引用:
i.一个源文件最多只能有一个包定义,如果有包定义必须出
现在文件的最前头。
ii.包的引用通过关键子importo但对java.lang包(最基本
的语言处理类)不需要import。如,String类就是lang包
中的类。
iii.包与类相似也是有层次的。
如,java类库中顶层是java,下一层有awt、io、net等。
这些包又有下一层,如在awt包中还有image、peer、test
等。在引用这些包时通过.来实现其层次性。如要引用
image包,格式为:java.awt.image。另外,如在程序中需
要用到某个包中许多子包的类时则可以通过*来实现多
个包的引用。
如java.awt.*
则表示可以引用awt包中子包的类。
但通过*来引用包并没有引用包中其他包的public类,如
要引用java.awt.image包中的ImageFilter类则必须单独
使用import语句。
如:importjava.awt.*;
importjava.awt.image.*;〃或者import
java.awt.image.ImageFilter;
也可以在程序中引用一个类的时候加上包名,这样不需
要使用import语句:java.awt.image.ImageFilterimf;如果
一个程序中引用了多个包,而且有两个及更多的包中有
相同的方法,则必须在具体用到该方法时必须指明该方
法所属的包。
iv、java中提供的基本包类。
•java.lang最基本的语言处理类;
•java.io实现输入输出
•java.util;包含一些如特殊类;
•用于实现网络连接,与java.io合用实现对
网络文档的读写;
•java.applet用于创建可在支持java的浏览器中运
行的javaApplet;
•java.awt可创建平台独立的图形用户接口(GUI)
程序
3、内部类(InnerClass):
a)内部类产生的意义:
Java中不允许实现类的多重继承,但当一个类需要实现多个类
中方法时,我们可以选择通过实现接口来达到这样的目的。但
在实现接口时必须实现该接口中所有的方法,这样有时会很烦
琐,故此Java中就增加了一个新的概念:内部类(InnerClass)。
在JDK1.1版以后就支持了内部类(InnerClass)o比如:在用
到AWT编程过程中,在需要处理多个事件时(如鼠标的点击
事件就有左、右、中等几种方法)就需要一个类能够使用多个
事件适配器类的方法,根据Java中不能实现多重继承的特性,
只能实现这些事件的监听器接口,但接口又要求必须实现其中
所有的方法,这样又很烦琐。
b)内部类的定义:
内部类就是嵌套在类中的类。
c)内部类的特性:
i.InnerClass一般用在定义它的类或语句块之内,在外部引
用它时必须给出完整的名称。InnerClass名字不能与包含
它的类名相同。
ii.InnerClass可以使用包含它的类的静态和实例成员变量,
也可以使用它所在方法的局部变量。
iii.InnerClass可以定义为Abstract的。
iv.InnerClass可以声明为private或protectedo
v.InnerClass若声明为static,就变成了顶层类,就不能使用局
部变量。
vi.InnerClass中的成员不能声明为static,只有在顶层类中才
能声明static成员。如果想在InnerClass中声明任何static
成员,则该InnerClass必须声明为static。
vii.建立内部类的对象:
1、在外部类的实例成员方法中可以直接建立内部类的
对象,不能在类方法中建立。
2、在外部类的类(static)成员方法中,以及与外部类
并行的其他类中的方法中,建立内部类对象必须与外
部类关联。outer.inner
viii.内部类的使用周期;
内部类定义在一个具体的语句块中,内部类只能在该语句
块的生命周期内存取该语句块中的局部变量。
d)事例:
importjava.awt.*;
importjava.awt.event.*;
publicclassTwoListenInner{
privateFrame;
privateTextFieldtf;
publicstaticvoidmian(Stringargs[]){
TwoLisenlnnerthat=newTwoLisenInner();
That.goQ;
)
publicvoidgo(){
f=newFrame(t4TwoListenerexample");
f.add("North”,newLabel(uClickanddragthemouse^^));
tf=newTextField(30);
f.addMouseMotionListener(newMouseMotionHandler());
f.addMouseListener(newMouseEventHandler());
f.setSize(3OO,3OO);
f.setVisible(true);
)
publicclassMouseMotionHandlerextendsMouseMotionAdapter{
publicvoidmouseDragged(MouseEvente){
Strings="Mousedragging:X="+e.getX0+“Y="+e,getY();
tf.setText(s);
)
)
publicclassMouseEventHandlerextendsMouseAdapter{
publicvoidmouseEntered(MouseEvente){
Strings="themouseEntered^^;
tf.setText(s);
)
publicvoidmouseExited(MouseEvente){
Strings="themousehasleftthebuilding^^;
tf.setText(s);
)
)
e)与内部类相关的概念还有内部接口和内部抽象类,其使用和概
念与内部类几乎一致,在此不赘述!
4、Java与C/C++的比较:
Java使用了类似于C/C++的语法,而去除了C/C++的许多不合
理的内容,以实现其简单、鲁棒、安全性等特性。
a)全局变量
Java中不能定义全局变量,只能通过类中的公用、静态的变量
实现全局变量。这样便保证了更好的安全性,全局变量被封装
在类中。而C/C++中,依赖于不加封装的全局变量常造成系统
的崩溃。(在引用类中私有变量和公用变量时,造成变量名称
的混乱,从而造成系统内存的错误)
b)无条件转移指令
与C/C++不同,Java不支持goto语句,而通过例外处理语句
try、catch、final等来代替C/C++中的goto语句,以处理遇到
错误跳转的情况,使程序更加结构化提高了程序的可读性。
c)指针
指针是C/C++中最灵活,但也是最容易出错的数据类型。以指
针进行内存操作常造成不可预知的错误。而且,通过指针对内
存进行显示类型转换后,可以访问类的私有变量,破坏了安全
性。Java中,程序员不能进行任何指针操作,同时一,数组在java
中用类来实现很好地解决了数组越界这个C/C++中不作检查
的错误。
d)内存管理
C中,程序员使用库函数malloc()和free()来分配和释放内存,
C++中则是运算符new和delete。再次释放已释放的内存块或
释放未分配的内存块,会造成系统的崩溃,而忘记释放不再使
用的内存块也会逐渐耗尽系统资源。在Java中,所有的数据
结构都是对象,通过运算符new分配内存并得到对象的使用
权,而实际上分配给对象的内存可随程序运行而改变。Java
自动进行管理并进行自动垃圾收集。有效的防止了因程序员误
操作而造成的错误,并更好的利用了系统资源。
e)数据类型的一致性
在C/C++中,不同平台上,编译器对简单的数据类型如int、
float等分别分配了不同的字节数。例如,int在IBMPC上为
16位,在VAX」1上为32位,因此导致了代码的不可一移植。
而在Java中,对某种数据类型总是分配固定的位数,这就保
证了Java的平台无关性和可移植性。
f)类型转换
在C/C++中,可以通过指针进行任意的类型转换,导致不安全
的可能性存在。在Java中,系统要对对象的处理进行相容性
的检查,防止不安全的转换。
g)头文件
在C/C++中使用头文件声明类的原型和全局变量及库函数等。
大的系统中,维护这些头文件非常困难。Java不支持头文件,
类成员的类型和访问权限封装在一个类中,运行时系统对此访
问进行控制。防止对私有成员的操作。另外,Java中用import
语句与其他类进行通信,以使用他们的方法。
h)结构和联合
C/C++中的结构和联合的成员均为公有,带来了安全性的问
题。Java不支持结构和联合,所有内容封装在类中。
i)预处理
C/C++中用宏定义实现的代码影响了程序的可读性。Java不支
持宏,以关键字final声明常量。
第八章异常处理
1、概念的产生:
在C/C++这样的语言中,对运行时间错误的处理可以有多种
形式,比如访问了一个无效指针,系统要么退出程序,告诉
你一个错误信息,要么系统死机。如果用函数处理所发生的
错误,必须有一个特定的返回值来通知函数调用者错误的发
生,或使用输出变量来辨认错误。总之,整个对错误的处理
不一致。为了能够有效处理程序运行错误,就必须建立统一
的机制来捕捉、处理异常。JAVA采用的面向对象方法处理
异常则解决了这个问题。
2、Java例外(异常):
eg8.1
importjava.io.*;
classExceptionDemo1{
publicstaticvoidmain(Stringargs[]){
FilelnputStreamfis=newFileInputStream("text");
intb;
while(b=fis.read()!=-1){
System.out.print(b);
)
fis.close();
此事例进行编译时系统将报错。(具体报错参看编译显示)
eg8.2
classExceptionDemo2{
publicstaticvoidmain(Stringargs[]){
inta=0;
System.out.printin(5/a);
)
)
此事例编译时没有报任何错误,但在执行时报错。
上面所举之两个实例,我们所遇到的所谓报错就是Java中所
提的异常(例外)。编译、运行时所报的错误信息显示的内容
java.io.FileNotFoundExceptionJava.io.IOException以及
java.lang.ArithmeticException分别指明了例外的类型。其概念
也正如类的概念。同时,从实例8.1和8.2报出例外的过程可
以看出,有些例外在程序中必须处理,否则编译都不通过
(eg8.1)o而有些例外在程序中可以不做处理,而直接由系统
运行时系统来处理(eg8.2)。
由此,则引出了我们下面将要讨论的例外的处理问题。
3、例外的处理机制:
在Java程序如果在运行中出现了例外就会生成一个例外对象。
这个对象可能是由正在运行的方法生成,也可能是Java虚拟机
生成,其中包括一些信息指明例外事件的类型以及当例外发生
时程序的运行状态等。生成的例外对象将传递给Java运行时系
统,这一例外的产生和提交的过程称为抛弃(throw)例外。
当Java运行时系统得到这个例外对象时,将会寻找处理这个例
外的代码。寻找按照方法的调用栈逐层上升。这个过程称为捕
获(catch)例外。如果捕获不到则程序停止。如8.2。
4、例外类的层次
由于Java处理例外采用了面向对象的思想,则整个例外自然包
含了层次性。这里Java将所有例外类对应于类Throwable及其
子类。具体层次结构见下图:
从上面的图我们看出,Java中的异常事件分为两类。一类继承
于类Error,通常这种例外程序是不应该捕获的例外,也不抛弃
这种例外。另外一类继承Exception的例外则是需要大量处理的
例外。
在Exception类下面的子类中,继承于RuntimeException的类代
表了程序运行时生成的例外。如eg8.2中产生的
ArithmeticException□这种例外比较普遍而且系统自身就能够处
理,所以不用程序员去用代码处理。而其它继承于Exception的
子类则代表非运行是例外。如eg8.1。这种例外程序必须处理。
下面我们将要讨论的例外处理就是针对这部分例外而进行的。
5、例外处理:
异常的处理可以有以下儿种:对运行时异常可以不做处理;使
用try-catch-finally语句捕获异常;通过throws子句声明异常,
还可以定义自己的异常类,并用他throw语句抛出它。
其中,try-catch-finally语句其语法为:
try{
.……〃可能产生例外的代码段
}catch(ExceptionName1e){
......〃捕获异常
}catch(ExceptionName2e){
......〃捕获异常
}finally{
.....〃不管是否有异常必须执行的代码段,一般是处理一些善
后事情
)
另外,如果在一个方法中生成一个例外,但是这个方法并不确
切知道该如何对这个例外进行处理,此时一般就由调用它的这
个方法来处理。这时一个方法就得声明抛弃例外使得例外对象
可以从调用栈向后传播,直到被捕获。声明抛弃例外是在一个
方法声明中的throws子句来指明并由合适的程序代码来处理,
当然也可以不处理。但是,对于非运行状态的例外必须处理:
例如:publicintread()throwsIOException{
)
同时一,我们在捕获一个例外前,例外都是通过throw语句抛出
的。只是抛弃例外可以是自己写的Java代码、JDK中的某个类
或者是Java运行时的系统。一般如果我们自己定义例外,则需
要自己写代码将此例外抛出供程序捕获。注意:用throw语句
抛出例外首先要生成例外对象,并且该例外必须是throwable
类或子类。
例如:lOExceptione=newIOException();〃生成例外对象
throwe;
thrownewString("wanttothrow")由于String并不是
throwable或子类,所以该错误。
eg8.3
importjava.io.*;
classExceptionDemo{
publicstaticvoidmain(Stringargs[])throwslOException{
〃通过throws语句抛弃lOException例外
FilelnputStreamfis=null;
try{〃可能产生例外的代码段
System.out.println("firstarguments"+args[O]);
fis=newFileInputStream("text");
System.out.println("contentoftextis:");
intb;
while((b=fis.read())!=-1){
System.out.println((char)b);
)
}catch(FileNotFoundExceptione){〃捕获例外
System.out.println(e);
}catch(lOExceptione){
System.out.println(e);
}catch(IndexOutOfBoundsExceptione){
System.out.println(e);
}finally{//必须执行的代码段
if(fis!=null){
System.out.println("closingFilelnputStream,
fis.close();
}else{
System.out.println("FileInputStreamnotopen");
注意:1)在try语句中产生例外对象后,系统会将该例外对象沿
调用栈向上寻找相匹配(是指参数类型与例外对象的类型完
全相同或者为其父类)的catch语句。所以,捕获例外的顺
序是和不同catch语句的顺序有关了。因此,在安排catch语
句顺序时必须是从特殊到一般。(如上例中,
FileNotFoundException是lOException的子类)(在下面的例
子中,如果调换两个catch语句的顺序则编译报错)
importjava.io.*;
publicclassQuizl{
publicstaticvoidmain(Stringarg[]){
inti;
System.out.print("GO");
try(
System.out.print("in");
i=System.in.read();
if(i=='0'){thrownewMyException();}
System.out.print("this");
)
catch(IOExceptione){}
catch(MyExceptione){
System.out.print("that");
)
System.out.print("way. ");
)
}
classMyExceptionextendsException{}
运行该程序后输入字符'O',请问运行结果为何?
(A)Gointhisway
(B)Gointhatthisway
(C)Gointhat
(D)Gointhatway
第十二、十三章图形用户界面
通过GUI(GraphicalUserInterface),用户和程序可以友好地进行
交互。Java中的AWT和Swing就包含了很多的类来支持GUI的设
计。AWT的主要功能:用户界面组件、事件处理模型、图形和图象
工具、布局管理器等。
1、生成Java图形用户界面
根据课本图12.2所示,在java.lang.object包之下有很多实现图
形用户界面的包和类,其中,Component类为java.awt包中最核
心的部分。它是构成Java图形用户界面的基础,其他所有组件都
是由这个类派生出来的。Component类是个抽象类(说明?),
不能直接使用。在Component类中,定义了AWT组件所具有的
一般功能(说明?)o
1)基本的绘画支持
方法repaint。、paint。、update。等用来在屏幕上绘制组件。
组件的绘制过程是不能被中断的,AWT绘图系统通过一个单
独的线程来控制程序何时进行组件的绘制。程序中也可以通
过调用repaint。来实现绘画,方法repaint。首先调用update()
进行背景清除,然后由update。调用paint。进行绘图。(在
Applet的动画程序体现)
2)外形控制(字体getFont。,颜色getColorModel等)
3)大小和位置控制
组件大小和位置主要取决组件所处的容器的布局管理器,但
组件本身也能够有自己的方法实现大小、位置的控制。
setSize()>setLocation。等
4)图象处理
类Component实现接口ImageObserver,其中方法
imageUpdate。用来图象跟踪。
5)组件状态控制
可用setEnable()>可视setVisible。、isVisible。返回组件状态等。
6)Container类的功能:
i.组件管理:add。添加组件、remove。删除组件
countComponent()用来统计容器内组件的个数,
getComponent。获得某个组件,paintComponents。绘制
容器内所有组件。
ii.布局管理:每个容器都和一个布局管理器关联。容器
通过setLayout。设置某种布局。
2、容器与组件:
常见的组件类:button、Label等,常用的容器有Frame>Panel、
Applet等o
Java的图形用户界面最基本的部分是组件,组件是以图形化
方式显示在屏幕上,并能够与用户交互。组件不能对显示,
必须将组件放在一定的容器中才能显示。容器实际就是
Component的子类,所以,容器本身也是个组件。
在容器中放置组件安排其位置和大小,必须注意:
1)容器中布局管理器负责组件的大小和位置,用户无法在
有直接通过程序的方法setLocation()>setSize。等来改
变,这样都会被布局管理器覆盖。
2)如果用户一定要改变,则必须首先将布局管理器取消
setLayout(null)o随后通过组件方法改变。但这样做的结
果是程序的系统相关。
java.awt中提供的常用容器中:
1)Frame(框架)类是Window类的子类,它是窗口的一种,
有自己的标题,其缺省布局管理器为BordeLayout,在
一个程序中我们可以使用多个Frameo注意:一个Frame
刚被创建后,其初始大小为(0,0)而且是不可见的,所
以必须重设其大小,并且用setVisible(true)设置其为可
见。
2)Panel(画板)无法独立显示,必须添加到某个容器中。
Panel缺省的布局管理器为FlowLayouto
例:
importjava.awt.*;
publicclassExgui{
privateFramef;
privatePanelp;
privateButtonbw,bc,be;
privateButtonbfile,bhelp;
publicstaticvoidmain(Stringargs[]){
Exguigui=newExgui();
gui.go();
)
publicvoidgo(){
f=newFrame("GUIexameple");
bw=newButton("WEST");
bc=newButton("Workspaceregion");
be=newButton("Exit");
f.add(bw,"West");
f.add(bc,"Center");
p=newPanel();
f.add(p,"North");
bfile=newButton("File");
bhelp=newButton("help");
p.add(bfile);
p.add(bhelp);
f.pack。;//将Frame设置为紧凑格式
f.setVisible(true);
}
3、AWT的事件处理
AWT编程的思想就是通过各种各样的组件实现GUI,并且能
够实现和用户的交互。整个实现的过程充分体现的是面向对
象的思想。然而,整个用户交互的过程就是用户触发事件,
事件就是发生在用户界面上的用户交互行为所产生的一种效
果。
JDK1.1中的AWT处理事件由原来JDK1.0的事件传递改为事
件授权模型,即事件处理从一个事件源授权到一个或多个事
件监听器,组件作为事件源可以触发事件,通过
addXXXListener方法向组件注册监听器,一个组件可以注册
多个监听器,如果组件触发了相应的事件,此事件就被传送
以注册的监听器,事件监听器负责处理事件过程。
ActionEvent
actionPerformed(ActionEvent)
Frame监听器对象
使用授权处理模型进行事件处理的实现原理:(见课本P294)
在AWT中的事件共10类(课本P295),其中ActionEvent>
ItemEventAdjustementEventTextEvent为高级事件,其余为
低级事件。高级事件封装了GUI组件的语义模式,他们没有
同任何屏幕基础的组件相连,而是与具有一定语义的事件相
连。如ActionEvent能在按钮按下时被激活,也能在用户在
TextField组件敲回车时被激活。所以高级事件又叫语义事件。
4、Swing和AWT的区别:
Swing是AWT的发展,它具备了许多AWT所不具备的功
能,如可以显示图标等。在具体的使用过程中一般没有什
么特别强调,通常都用Swingo
5、AWT和Swing的区别
例:
importjavax.swing.*;
publicclassswing1{
publicstaticvoidmain(Stringargs[]){
JFrameframe=newJFrame("helloworld");
finalJLabellable=newJLabel("helloworld");
frame.getContentPane().add(lable);
frame.setSize(200,200);
frame.setVisible(true);
)
}
第十一章线程
1、线程的产生:
在Java语言产生前,传统的程序设计语言的程序同一时刻只能
单任务操作,效率非常低,例如程序往往在接收数据输入时发
生阻塞,只有等到程序获得数据后才能继续运行。随着Internet
的迅猛发展,这种状况越来越不能让人们忍受:如果网络接收
数据阻塞,后台程序就处于等待状态而不继续任何操作,而这
种阻塞是经常会碰到的,此时CPU资源被白白的闲置起来。如
果在后台程序中能够同时处理多个任务,该多好啊!应Internet
技术而生的Java语言解决了这个问题,多线程程序是Java语
言的一个很重要的特点。在一个Java程序中,我们可以同时并
行运行多个相对独立的线程,例如,我们如果创建一个线程来
进行数据输入输出,而创建另一个线程在后台进行其它的数据
处理,如果输入输出线程在接收数据时阻塞,而处理数据的线
程仍然在运行。多线程程序设计大大提高了程序执行效率和处
理能力。
计算机操作系统多任务的处理方式给程序设计提出了新的发展
方向,就是程序如何同样实现并行的处理?Java语言就是根据
操作系统的多任务性设计出可支持多个程序片段并行运行的机
制,即Java的多线程技术(此技术也是Java的重要特性之一)。
操作系统中的多任务是通过进程来控制,每个任务对应一个进
程,而Java中是通过线程来控制多任务的执行。
线程与进程的区别:
a)进程:每个进程都有独立的代码和数据空间,进程切换的开销
大;
b)线程:轻量的进程,同一类线程共享代码和数据空间,每个线
程有独立的运行栈和程序计数器,线程切换的开销小;
c)多进程:在操作系统中,能够同时运行多个任务(程序);
d)多线程:在同一个应用程序中,有多个顺序同时执行;
e)一个进程中可以包括多个线程;
2、线程的概念:
线程是一个程序内部的顺序控制流。
在前面所举的简单例子中,我们是对字符串进行处理,它的特
点是每个程序都有一个入口、一个出口以及一个顺序执行的序
歹U,在程序执行过程中的任何指定时间内,都只有一个单独的
执行点。线程也是只有一个入口、一个出口和一个顺序执行的
序列,但线程并不是程序,不能够单独运行,必须在程序中运
行。从概念上讲一个线程就是一个程序内部的顺序控制流。一
个线程是没有意义的,真正发挥作用的是在一个程序中实现多
个线程。
在多任务的Windows系统中,计算机可以同时执行多个程序,
而多线程则是在一个程序内部又可以同时进行多种运算。从逻
辑上讲,多线程意味着一个程序的多行语句同时执行,但是多
线程不等于多次启动一个程序,操作系统也不会把每个线程当
作进程对待。(具体事例描述见课本P245)
线程的概念模型:
1)虚拟的CPU,封装在java.lang.Thread类中;
2)CPU所执行的代码,传递给Thread类;
3)CPU所处理的数据,传递给Thread类;
理解:由于在实现线程时引用的包中必须有Run()方法,此方法
就代表启动CPU来处理这部分顺序代码,故此称为虚拟CPU;
而在定义线程时,线程要执行的代码和运算的数据就必须都传
给Thread类。
3、线程的使用:
a)线程体:Java的线程是通过Java的软件包java.lang中的类
Thread来实现的。当我们生成一个Thread类的对象之后,一
个新的线程就诞生了。这个线程实例表示Java解释器中真正
的线程,并作为控制和同步执行的一个句柄,通过它可以启动
一个线程、终止线程、或者暂停挂起它等。每个线程都是通过
某个特定对象的方法run()来完成其操作的,方法run()称为线
程体。在一个线程被建立并初始化以后,Java的运行时系统就
就可以启动线程start。,自动调用run()方法执行线程体。run()
方法就是线程执行的起点,象应用程序从main()开始、小应
用程序从init()开始一样。通常run()方法为一个循环。
b)线程体的构造:
正如课本P256中所提,构造线程通过在Java的软件包
java.lang中的类Thread来提供的构造方法:
publicThread(ThreadGroupgroup,Runnabletarget,String
name),其中,group指明该线程所属的线程组;target为实际执
行线程体的目标对象,它必须实现接口;name为线程名。在
此体现面向对象的思想,通过Tread()方法的多态性来根据实
际情况构造不同情况的线程即同一个方法有不同的参数。需要
解释的是线程体目标对象:前面提到线程是程序中的一段代
码,不能够单独运行,必须在程序中才能运行。在此提到的线
程体目标对象就是包含该线程体的类。
一个类声明实现Runnable接口,就意味着该类可以作为线程
体的目标对象。Runnable接口只定义了一个方法run()作为线
程体的构造空间。
由于类Thread本身也是实现了接口Runnable,因此可以通过
两种方法实现线程体。
1)定义一个线程类,它继承类Thread并重写其中的方法
run(),这时在初始化这个类的实例时,目标target为null,
表示由这个实例来执行线程体。
2)提供一个实现接口Runnable的类作为一个线程的目标对
象,在初始化一个Thread子类的线程对象时,把目标对
象传递给这个线程实例,由该目标对象提供线程体
run()o
3)两种方法定义的线程实例见课本。
两种方法的比较:
1)使用Runnable接口
1.可以将CPU、代码和数据分开,形成清晰的模
型。在例子中,Thread对象clockThread中封装
了CPU、类Clock提供了线程执行的代码,当前
的Clock类实例this提供了线程运行时需要的
数据。
2.还可以继承其他类。
3.保持程序风格的一致性。
2)直接继承Thread类
1.不能继承其他类。
2.编写简单,可以直接操作线程,无须使用
Thread.currentThread()。
3.事例:
//通过Thread类的子类创建的线程;
classthread1extendsThread
{file:〃自定义线程的run。方法;
publicvoidrun()
(
System.out.println("Thread1isrunning---");
)
)
file:〃通过Runnable接口创建的另外一个线程;
classthread2implementsRunnable
{file:〃自定义线程的run()方法;
publicvoidrun()
(
System.out.println("Thread2isrunning---");
)
)
file://程序的主类’
classMulti_Threadfile://声明主类;
(
plubicstaticvoidmail(Stringargs[])file:〃声明主方法;
threadlthreadone=newthreadl();file://fflThread
类的子类创建线程;
Threadthreadtwo=newThread(newthread2());file:〃用
Runnable接口类的对象创建线程;
threadone.start();threadtwo.start();file:〃strat()方法启
动线程;
)
)
运行该程序就可以看出,线程threadone和threadtwo交替占用CPU,
处于并行运行状态。可以看出,启动线程的run()方法是通过调用线
程的start。方法来实现的(见上例中主类),调用start。方法启动线程
的run()方法不同于一般的调用方法,调用一般方法时,必须等到一
般方法执行完毕才能够返回start。方法,而启动线程的run()方法后,
start。告诉系统该线程准备就绪可以启动run()方法后,就返回start()
方法执行调用start。方法语句下面的语句,这时run()方法可能还在
运行,这样,线程的启动和运行并行进行,实现了多任务操作。
c)线程的状态:
线程作为一段可执行的程序段落,它的存在必然有个生命周
期。在一个线程的生命周期中它总是处于不同的状态。线程的
状态表示了线程正在进行的活动以及在这段时间内线程能完
成的任务。
线程状态图
1.创建状态(newThread)
声明方法:ThreamyTread=newMyThreadClass();
状态说明:由于没有启动这个线程,所以线程处于创建状
态时:它仅仅是个空的线程对象,系统不为其
分配资源。
可行操作:启动身体start。或终止stop()o
2.可运行状态(Runnable)
声明方法:ThreadmyThread=newMyThreadClass();
myThread.start();
状态说明:start。方法产生了运行这个线程所需的系统资
源,安排其运行,并调用线程体——run()方法。
可运行状态并不是运行中状态(单处理器所
致),但可以随时运行,不需要程序再去控制,
系统自动调度。
可行操作:yield。暂时挂起该线程,使其它优先级较高的
线程先运行。
stop。或run()exits停止线程。
3.不可运行状态Runnable:
当下面四种情况发生时,线程处于不可运行状态:
a)调用sleep。方法
b)调用suspend。方法
c)为等待一个变量,线程调用wait()方法
d)输入输出流中发生线程阻塞
如课本中的实例代码中的:myThread.sleep(10000),就是使
该线程休止10秒,这时即使处理器空闲,也不能执行该线
程,10秒后线程又成为可运行的。
对上面四种情况,都有特定的返回可运行状态的方法与之
对应。对应方法如下:
1.如果线程处于睡眠状态中,sleep。方法中的参数为休息
时间,当这个时间过去后,线程即可运行。
2.如果一个线程被挂起,须由其他线程调用resume。方法
来恢复该线程的执行。
3.如果线程在等待条件变量,那么要停止等待的话,需要
该条件变量所在的对象调用notify。或notifyAU()方法。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/1521.html