第一章 java 语言概述
Post on 19-Mar-2016
149 Views
Preview:
DESCRIPTION
TRANSCRIPT
第一章 Java语言概述
HUST & IBM Computer Tech. Center
主要内容提要
Java程序的开发环境
Java 程序相关问题
Java语言的主要特性
Java 语言的发展历史
Java 程序的开发过程
HUST & IBM Computer Tech. Center
Java语言的发展历史
Internet迅猛发展 Java语言正式问世被美国著名杂志 PC Magazine评为 1995年十大优秀科技产品之一
James Gosling领导的Green小组开发了面向数字家电的Oak语言
推出了 Java2平台。性能上有所提高,而且对Java的基本模式进行了完善,并提供了更为丰富的 API
1991 1995 1998
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java2 的版本划分
Java 2Java 2
J2MEJ2ME
J2SEJ2SE
J2EEJ2EE
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java语言的主要特性
平台无关性
简单性
面向对象
分布式、动态性、 可靠性、安全性 ……
多线程
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java ——程序相关问题 Java虚拟机
硬件平台
操作系统
J ava程序
Java虚拟机
J ava API
Java虚拟机——在真实机器中用软件模拟实现的一种抽象的机器。( Java 虚拟机规范)
Java虚拟机主要由五个部分组成:指令系 统、寄存器、栈、存储区、碎片回收区
解释和执行 Java程序编译后产生的字节码
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java ——程序相关问题 Java API
硬件平台
操作系统
J ava程序
Java虚拟机
J ava API
Java API是 Java系统提供的预先定义好的软件组件的集合,它们提供了许多可供程序员调用的常用功能
丰富的 API 为程序员提供了极大的方便,但也是学习的难点要学会使用 Java API手册 (The Java 2 Platform API Specification )
http://java.sun.com/j2se/1.5/docs/api/index.html
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java ——程序相关问题 Java程序的运行机制
操作系统操作系统源代码 可执行代码目标码
编译 连接 运行
源代码 字节码
编译 解释执行
JJavaava解释器解释器
传统语言的运行机制
Java语言的运行机制
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java ——程序相关问题 Java程序类型 Java应用程序( Java Application)
是独立完整的程序 在命令行调用独立的解释器软件即可运行 主类必须有 main 方法,这也是程序的入口
Java小程序 Java Applet——是指在客户端运行的 Java小程序,一般来说客户端是指用户所使用的浏览器
Java Servlet——是在服务器端执行的 Java小程序,为了能够支持 Servlet的运行,服务器端必须安装包含 Java虚拟机的服务器软件,这种能够支持服务
端小程序的服务器一般被称为应用服务器
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java开发环境JDK/J2SDK( Java Developer Kit)
JDK1.02 JDK1.1.x JDK1.2/J2SDK1.3/J2SDK1.4/JDK5.0(J2SDK1.5)
Java集成开发环境( IDE) NetBeans JBuilder Eclipse JCreator Forte for Java Visual J++ WSAD ……
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
JDK的安装与设置
从 http://java.sun.com/可以下载相 关版 本的 JDK(本课程采用 J2SDK1.3以
上版本)在 Windows平台上运行安装程序,以安装JDK
设置 PATH(文件路径)参数。由于 JDK提供的实用程序都在安装目录下的子目录bin下,为了能在任何目录下直接使用文件名调用这些程序,必须设置操作系统的文件路径参数
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
环境设置
在Windows环境下,为了快速进入指定目录的命令行窗口,可在注册表中增加项目:
[HKEY_CLASSES_ROOT\Directory\shell\进入命令行 \command]默认值设为:
cmd /k "cd %1"
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
JDK的目录结构
bin目录中包含了所有 JDK5.0提供的实用程序demo目录中包含了 JDK5.0自带的实例程序inculde目录中包含了一些支持 Java native方法的 C\C++头文件jre目录中包含了 Java运行环境所需的所有文件,这个目录中所包含的 java运行环境是 JDK私有的,它只为 JDK的实用程序提供支持lib目录中包含了 Java开发环境所需的库文件,它们以 jar文件的形式保存sample目录中包含的是体现JDK5.0 新特性的一些例程
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
JDK实用程序简介 javac: Java编译器,将 Java源代码编译为字节码; java: Java解释器,用来解释执行 Java程序的字节码文件;
appletviewer(小程序浏览器 ):一种执行 HTML文件上的 Java小程序类的 Java浏览器;
javadoc:根据 Java源代码及其说明语句生成的 HTML文档;
jdb: Java调试器,可以逐行地执行程序、设置断点和检查变量;
javah:产生可以调用 Java过程的 C过程,或建立能被Java程序调用的 C过程的头文件;
javap: Java反汇编器,显示编译类文件中的可访问功能和数据,同时显示字节代码含义。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java程序的开发过程
编辑源代码
编译源代码文件
运行程序
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java ——程序的开发过程 编辑源代码
一般情况下,我们可以使用系统平台下的任何文本编辑器进行源代码的编辑,在 Windows平台下常用的是Window “ ” “ ” 系统自带的 记事本 程序或 写字板 程序
Java源码大小写敏感 Java源码文件的扩展名: .java Java源程序文件也不能随意命名,其文件名必须与程序
中主类的类名完全相同,包括大小写在内
public class MyFirstJavaApp { public static void main(String[] args) { System.out.println(“This is My First Java Application!”); }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java ——程序的开发过程 编译源代码
使用 JDK实用程序 javac对源代码文件进行编译 C:\MyJava>javac MyFirstJavaApp.java 如果系统提示符再次出现并且没有任何消息产生,那么编译便成功了
如果有系统报错消息产生,则表示程序编译出错,程序员必须阅读报错信息,并根据这些信息对程序进行修改
程序成功编译后,在与源代码文件同一目录下会生成一个新的文件,其文件名与源代码文件名相同,
“扩展名为 .class”。这个文件就是源代码文件编译产生的程序字节码文件 MyFirstJava.class
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java ——程序的开发过程 运行程序
要执行一个 Java程序非常简单,只需在字节码文件所在目录下输入下列命令就可以了 : java 字节码文件名
第 2 章 面向对象的编程概念华中科技大学 IBM 技术中心 2006
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
主要内容提要
什么是接口
什么是继承
什么是类
什么是消息
什么是对象
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
面向对象 vs. 面向过程面向对象( OOP ——) Object-Oriented Programming 用类 class封装数据以及与数据相关的操作 用类的继承性来实现类的重用性 多态性 “ ”面向 对象 ,由对象提供服务
面向过程( POP ——) Procedure-Oriented Programming 以功能为组织单元 通过数据结构来描述具体的问题 数据在功能 (函数 )之间以参数的形式被传送
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
现实世界中的对象
现实世界是由对象构成的 现实世界中任何实体都可以看作是对象现实世界中的对象有两个共同特征:
状态 行为
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
软件对象(Object)软件对象是现实世界对象的抽象软件对象同样具有状态和行为定义:对象是变量和相关方法的软件组合
变量
方法
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
现实对象→软件对象
方法
叫
咬
吃
是否饿了:否
名字:小 Q
颜色:黑
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
封装( Encapsulation)封装性体现了面向对象程序设计的一个特性,将方法和数据组织在一起,隐藏其具体实现而对外体现出公共的接口 模块化 隐藏信息 变量
方法
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
消息(Message)
复杂的行为必须通过对象之间的交互来实现
软件对象与其它对象进行交互与通讯是通 过互发消息来实现的
对象B
对象 A 消息
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
消息的组成
消息的目的对象要执行的方法的名称方法所需参数
你的车 你 换档(低档)
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
消息的性质
同一对象可接收不同形式的多个消息,产生不同的响应
同一个消息可以发给不同的对象,所做出的响应可以截然不同
发送方不需要知道接受方如何对请求予以响应的
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
类( Class)定义:类是蓝图或原型,它定义了所有某种类的对象的共有的变量和方法
类是具有共同属性和行为的对象的抽象与集合
私有的实现细节
公共 API
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实例( Instance)定义:特定类所描述的一个具体对象
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
对象、类与实体的关系
对象
类计算机逻辑的实现
映射计算机世界
实例化 抽象
实体
抽象数据类
现实世界
概念世界
抽象
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
继承( Inheritance)广义地说,继承是指能够直接获得已有的性质和特性,而不必重复定义它们。在面向对象的软件技术中,继承是子类自动地共享父类中定义的数据和方法的机制。
共性部分
继承部分
个性部分
父类
子类
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
单重继承与多重继承
单重继承:一个子类只有一个唯一确定的父类 单重继承所构成的类的关系结构是一棵树
多重继承:一个子类可以有多个不同的父类 多重继承所构成的类的关系结构是一个格
Java语言仅支持单重继承
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
继承的作用
使软件系统具有开放性
更好地进行抽象与分类
实现代码的复用
提高可维护性
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
类型( Type)
在面向数值的编程中,类型通常用作数据的表示。在 Java这样的强类型语言中,在编译期,每一个变量和表达式都有一个类型与之相对应
Java中的类型:基本类型、类、接口
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
接口( Interface)接口和类一样也是一种类型,也同样包含一些方法的定义。但与类不同的是:接口中所定义的所有方法都是抽象方法(即没有实现的方法)。
接口中所定义的方法由实现( implement)该接口的类来实现,一个类可以同时实现多个接口
接口机制使 Java的面向对象编程变得更加灵活。解决了单重继承带来的问题
接口定义了对象的行为模型,相当于一个协议。实现接口的各个类负责实现接口所定义的行为。虽然实现细节各不相同,但对用户来说是一样的行为。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
面向对象的示例
本例中包含很多对象:点、窗口、颜色、点击事…… 件
代码: ClickMeApp.java , ClickMe.java,Spot.java
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Spot类public class Spot { //instance variables private int size; public int x, y; //constructor public Spot() { x = -1; y = -1; size = 1; }
//methods for access to the size instance variable public void setSize(int newSize) { if (newSize >= 0) { size = newSize; } } public int getSize() { return size; }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Spot对象
private Spot spot = null; ... spot = new Spot();
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
示例中的消息
g2d.setColor(Color.WHITE); g2d.fillRect(0, 0, getWidth() - 1, getHeight() - 1);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
示例中的继承和接口
public class ClickMe extends JComponent implements MouseListener { ... }
public class ClickMe extends JComponent implements MouseListener { ... //Methods required by the MouseListener interface. public void mousePressed(MouseEvent event) { if (spot == null) { spot = new Spot(); spot.setSize(RADIUS); } spot.x = event.getX(); spot.y = event.getY(); repaint(); } public void mouseClicked(MouseEvent event) {} public void mouseReleased(MouseEvent event) {} public void mouseEntered(MouseEvent event) {} public void mouseExited(MouseEvent event) {} } }
欢迎提问
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
变量( Variable)
对象将它的状态存储在变量中定义 : 变量是一个由标识符命名的数据项
变量名必须是一个合法的 标识符 --一个以字母开头的无限制的 Unicode字符序列。
变量的声明: 类型 名称 类型 名称 [ = [ = 初始值初始值 ]]; int i; double pi = 3.1415926; String name;
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
数据类型 每个变量都必须有一个数据类型 . 一个变量的数据类型决定了它能容纳的值和在它上面可以进行什么操作。
Java编程语言有两大类数据类型: 原始类型 (primitive) 引用类( reference)
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java的数据类型
Java type system
primitive reference
char numeric boolean class interface array
integer floating-point
byte short int long float double
Java type system
primitive reference
char numeric boolean class interface array
integer floating-point
byte short int long float double
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
原始类型变量包含单个值,其大小和格式与它的类型匹配:数字、字符或布尔值。
Java语言没有 unsigned类型 0xFFFF和 0xFF谁大?
Java语言必须强制类型转换 float f = 0.1; boolean b = 1;
原始类型
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
引用类型
数组,类和接口就是引用数据类型 .与原始类型变量的值不同的是,引用类型变量的值是对应变量代表的一个值或一组值的引用(也就是其地
址)在其他语言里引用被称为指针或者内存地址。 Java不支持显示地使用地址,而是使用变
量的名称代替。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
变量的引用
通过变量名引用变量的值简单名称:由单个标识符组成的名称限定名称:通过类名或对象名引用改类或对象中的成员变量 System.out.println(i+spot.x);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
作用范围
变量的作用范围是可以通过简单名称引用该变量的程序区域
作用范围也决定了系统为该变量创建和释放内存的时间
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例子
int i = 10;if ( i> 0) { int i = 20; System.out.println(“The value of i = ” + i); }System.out.println(“The value of i = ” + i);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
最终变量
你可以在任意范围里将一个变量定义为最终变量( final)
最终变量的值一经初始化就不能改变类似于 C语言中的常量 (const)
final int aFinalVar = 0;
final int blankfinal; . . . blankfinal = 0;
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
操作符、表达式、语句和块
自学!
第四章 对象基础和简单数据对象华中科技大学 IBM技术中心
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
主要内容
数组
数字
字符和字符串
对象的生存周期
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
对象的生命周期
对象的创建 对象的使用 对象的清除对象的创建 对象的使用 对象的清除
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
CreateObjectDeompublic class CreateObjectDemo { public static void main(String[] args) { //创建一个 Point对象和两个 Rectangle对象 Point origin_one = new Point(23, 94); Rectangle rect_one = new Rectangle(origin_one, 100, 200); Rectangle rect_two = new Rectangle(50, 100); // 显示 rect_one的宽、高以及面积 System.out.println("Width of rect_one: " + rect_one.width); System.out.println("Height of rect_one: " + rect_one.height); System.out.println("Area of rect_one: " + rect_one.area()); rect_two.origin = origin_one; //设置 rect_two的位置 // 显示 rect_two的位置 System.out.println("X Position of rect_two: " + rect_two.origin.x); System.out.println("Y Position of rect_two: " + rect_two.origin.y); // 移动 rect_two并且显示它的新位置 rect_two.move(40, 72); System.out.println("X Position of rect_two: " + rect_two.origin.x); System.out.println("Y Position of rect_two: " + rect_two.origin.y); }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
对象的创建
引用变量的声明 实例化对象 对象的初始化引用变量的声明 实例化对象 对象的初始化
类型名 引用变量 = new 构造器 (构造器的参数 )
① ③②
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
声明一个变量来引用对象
为了声明一个变量来引用对象,你可以使用类或者接口的名字作为变量的类型
声明并没有创建新对象。在对该引用变量赋值前,该引用为空 ,称为空引用 (null)
类型名 引用变量 = new 构造器 (构造器的参数 )
①
Point origin_one
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实例化对象
new操作符通过为新对象分配内存来实例化一个类
new操作符需要一个后缀参数,即构造器的一个调用
new操作符返回一个对它所创建对象的引用,通常该引用被赋值给具有适当类型的引用变量 如果 new操作符返回的引用没有被赋给任何变量,那么当 new操作符所在的语句执行完后,将无法访问该对象
类型名 引用变量 = new 构造器 (构造器的参数 )
① ②
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
初始化对象
构造器( Constructor):是一个用来创建对象的特殊方法,用来初始化对象的属性。 构造器的名字与类名相同 构造器没有返回值 构造器所包含的语句用来对所创建的对象进行初始化 “ ”没有参数的构造器称为 无参构造器 每个 Java类都至少有一个构造器,如果该类没有显式地声明任何构造器,系统会默认地为该类提供一个不包含任何语句的无参构造器
类型名 引用变量 = new 构造器 (构造器的参数 )
① ③②
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
对象创建的实例
public class Point { public int x = 0; public int y = 0; public Point(int x, int y){ this.x = x; this.y = y; } }
Point origin_one = new Point(23, 94);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问 题
Point origin_one = new Point(23, 94);
Point origin_two = new Point(23, 94);
oringin_one==oringin_twoPoint origin_one = new Point(23, 94);
Point origin_two =origin_two;
oringin_one==oringin_two
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
构造器的重载(Overload)public class Rectangle { public int width = 0; public int height = 0; public Point origin; public Rectangle() { origin = new Point(0, 0); } public Rectangle(Point p) { origin = p; } public Rectangle(int w, int h) { this(new Point(0, 0), w, h); } public Rectangle(Point p, int w, int h) { origin = p; width = w; height = h; } ……. }
一个类可以包含多个构造器,这种情况成为构造器的重载
同一个类中的多个构造器通过参数的数目及类型的不同来区分
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
对象的使用
对象的使用有两种方式 操作或者检查它的变量 调用它的方法
要使用对象的实例成员,首先需要得到该对象的引用 变量
方法
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实例成员与类成员
实例成员包括实例变量与实例方法 实例成员依赖于实例存在 同一个类的不同实例都拥有一份实例变量的拷贝,对某个实例的实例变量的操作不影响到其它实例
实例变量遵循对象的生命周期,随着对象的创建而创建,随着对象的消亡而消亡
必须通过实例的引用来调用实例方法类成员包括类变量与类方法
类成员不依赖于实例存在 同一个类的不同实例共享同一个类变量,对类变量的改变会影响到所有实例
类变量的生存期不依赖于对象,其它类可以不用通过创建该类的实例,直接通过类名访问它们。同样,类方法也可以直接通过类名访问。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实例成员与类成员
class ABCD { char data; static int share_data;}class Demo { ABCD a,b,c,d; … //实例化}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实例变量的引用
简单名称 当实例变量处在作用域内 (即对象的类的代码内 ) 的时候
限定名称 objectReference.variableName 当实例变量处在作用域外时使用限定名称
System.out.println("Width of rect_one: " + rect_one.width);System.out.println("Height of rect_one: " + rect_one.height);int height=new Rectangle().height;
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
关于变量访问的说明
建议不要通过其它对象或类直接操作对象的变量 ,可能引起无效值
理想情况下 ,类会提供一些方法 ,其他对象可以通过他们检查或修改变量,确保值有效,而且如果变量的类型和名称发生了变化,不会影响它的使用者
在某些情况下,可以允许对对象变量的直接访问,以使类更小更简单,也可使变量适用于更广泛范围;
JAVA编程语言提供了一个访问控制机制,通过这种机制,类可以决定那些其它的类可以直接访问它的变量(第五章中介绍)。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
调用对象的方法
使用限定名称来调用对象的方法objectReference.methodName(argumentList);或者objectReference.methodName();
System.out.println("Area of rect_one: " + rect_one.area());rect_two.move(40, 72);int areaOfRectangle = new Rectangle(100, 50).area();
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
关于方法调用
方法被声明为 public,就可以被任何其它的类所访问。有时,类需要限制对它的方法的访问
类可以使用与控制变量访问相同的机制来对它的方法进行访问控制(第五章中介绍)
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
对象的清除
JAVA运行时环境在当对象不再被使用的时“候清除它们,这个过程就是所谓的 垃圾收
”集 ( garbage collection)Java的垃圾收集器自动扫描对象的动态内存区,对被引用的对象加标记,然后把没有引用的对象作为垃圾收集起来并释放。
垃圾收集器作为一个线程运行。当系统的内存用尽或程序中调用 System.gc()要求进行垃圾收集时,垃圾收集线程与系统同步运行。否则垃圾收集器在系统空闲时异步地执行。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
无用对象的判定
当某个对象不在被任何引用变量引用时,该对象是无用对象,将被清除。一般有如下两种情况:引用变量超出了作用域{ StringBuffer s = newStringBuffer(“thisisatest”); ……}// 超出对象作用域……
引用变量引用了其它对象或引用了空对象StringBuffer s = new StringBuffer(“test1”); ……s = new StringBuffer(“test2”); // 引用了新的对象 ……s = null; // 引用为空
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
finalize()方法
在对对象进行垃圾收集前, Java运行时系统会自动调用对象的 finalize()方法来释放系统资源。
某些情况下,程序员可能需要实现该方法来释放不由垃圾收集器所控制的资源。但这种情况非常少见
finalize()方法是在 Object中有缺省实现,在用户自定义的类中,它可以被覆盖,但一般在最后要调用父类的 finalize()方法来清除对象所使用的所有资源
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题一
下列程序的运行结果?
public class SomethingIsWrong { public static void main(String[] args) { Rectangle myRect; myRect.width = 40; myRect.height = 50; System.out.println("myRect's area is " + myRect.area()); }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题二
现有一个 Point和 Rectangle对象,代码执行后有多少引用指向它们?有没有对象需要垃圾收集?
Point point = new Point(2,4);Rectangle rectangle = new Rectangle(point, 20, 20);point = null;
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
字符和字符串
Java API提供了三个处理字符数据的类:
Character:这个类的实例可以容纳单一的字符数值。该类还定义了一些简洁的方法来
操作或者检查单一字符数据。 String:这个类用于处理由多个字符组成的
不可变数据。 StringBuffer:这个类用于存储和操作由多个字符组成的可变数据。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
字符类( Character)
字符类的对象包含单个字符值
当需要使用对象时,可以用字符对象替代原始的 char类型的变量
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
——字符类 构造器和方法
Character(char)- Character类唯一的构造器,它创建一个字符对象,其中包含由参数提供的值,一旦创建了Character对象,它包含的值就不能改变。
compareTo(Character)-这个实例方法比较两个字符对象包含的值,这个方法返回一个整数值,表示当前对象中的值是大于、等于还是小于参数所包含的值
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
——字符类 构造器和方法
equals(Object)-这个实例方法比较当前对象包含的值与参数对象包含的值,如果两个对象包含的值相等,那么这个方法返回 true
toString()-这个实例方法将此对象转换为字符串
charValue()-这个实例方法以原始char值的形式返回此字符对象包含的值
isUpperCase()-这个实例方法判断一个原始 char值是否是大写字母
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
——字符类 例程
public class CharacterDemo { public static void main(String args[]) { Character a = new Character('a'); Character a2 = new Character('a'); Character b = new Character('b'); int difference = a.compareTo(b); if (difference == 0) { System.out.println("a is equal to b."); } else if (difference < 0) { System.out.println("a is less than b."); } else if (difference > 0) { System.out.println("a is greater than b."); } System.out.println("a is "+ ((a.equals(a2)) ? "equal" : "not equal")+ " to a2."); System.out.println("The character " + a.toString() + " is " + (Character.isUpperCase(a.charValue()) ? "upper" : "lower")+ "case."); } }
程序的输出:a is less than b.a is equal to a2.The character a is lowercase.
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
——字符类 类方法
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
Character a = new Character('a');Character b = new Character('a');
•下列 boolean表达式的值是 true还是 false?
( 1) a.compareTo(b)==0
( 2) a.equals(b)
( 3) a==b
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
字符串和字符串缓冲区
Java平台提供两个类 String和StringBuffer,它们用于存储和操作字符串-由多个字符组成的字符数据。
String类用于其值不能改变的字符串;StringBuffer类用于被修改的字符串,通常用来动态的构造字符数据。
字符串是常量,比字符串缓冲区更高效,而且字符串可以被共享。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
字符串( String)使用字符串常量时,需要创建 String对象,和其它对象不同, String对象可以通过简单赋值语句创建: String name = “Petter”;
此外,也可根据 String类的构造函数创建String对象: String name = new String(“Petter”);
对于程序任何位置出现的双引号标记的字符串,系统都会自动创建一个 String对象。
可通过 String对象的方法对字符串进行操作
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
——字符串 构造器
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
字符串的不可变性?
String类用于其值不能改变的字符串观察下列程序:
public class StringTest{ public static void main(String[] args){ String s="abc"; s=s+“defg"; System.out.println(s); }}
程序运行结果是 abc还是 abcdefg?
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
字符串的不可变性?
abcs
defg
“defg”
s+”defg”
abcdefg
s=s+”defg”
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
字符串缓冲区( StringBuffer)
String对象表示的是不可更改的字符串对象,如果需要修改 String对象所表示的内容,必须重新创建一个对象: String str = “Petter”; str = str + “ & Bob” + “ & Tom”;
当修改操作频繁,或字符串的值很大时,会额外分配大量内存
因此, Java语言引入了一个StringBuffer类,用来表示内容可以扩充和修改字符串对象
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
StringBuffer——构造器
必须使用 new操作符创建字符串缓冲区
String s = "Dot saw I was Tod";StringBuffer dest = new StringBuffer(s);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
访问器方法
用于获取关于对象的信息的方法被称为访问器方法。
字符串和字符串缓冲区都可以使用的一个访问器方法就是 length方法。
length方法返回字符串和字符串缓冲区中包含的字符数。
String palindrome = "Dot saw I was Tod"; int len = palindrome.length();
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
容量
在 StringBuffer类中还有一个capacity()方法,它返回分配给这个字符串缓冲区的容量,而不是使用量。使用量会改变,但是容量始终是不变的。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
通过索引得到字符
charAt()访问器方法,通过索引从字符串或者字符串缓冲区得到字符,索引值从零开始。String anotherPalindrome = "Niagara. O roar again!";
char aChar = anotherPalindrome.charAt(9);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
substring方法
如果要从字符串或者字符串缓冲区得到多个字符,可以使用 substring方法。
String substring(int) String substring(int,int)
String anotherPalindrome = "Niagara. O roar again!";
String roar = anotherPalindrome.substring(11, 15);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
search
string类提供两个访问器方法,返回特定的字符或者子字符串在字符串中的位置。
indexOf()方法从字符串的开头查找;lastindexOf()方法从字符串的末尾查找;
stringBuffer类不支持 indexOf()和lastindexOf()方法。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
search
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
search examplepublic class Filename { private String fullPath; private char pathSeparator, extensionSeparator; public Filename(String str, char sep, char ext) { fullPath = str; pathSeparator = sep; extensionSeparator = ext; } public String extension() { int dot = fullPath.lastIndexOf(extensionSeparator); return fullPath.substring(dot + 1); } public String filename() { int dot = fullPath.lastIndexOf(extensionSeparator); int sep = fullPath.lastIndexOf(pathSeparator); return fullPath.substring(sep + 1, dot); } public String path() { int sep = fullPath.lastIndexOf(pathSeparator); return fullPath.substring(0, sep); }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
search example
public class FilenameDemo { public static void main(String[] args) { Filename myHomePage = new Filename("/home/mem/index.html",'/', '.'); System.out.println("Extension = " + myHomePage.extension()); System.out.println("Filename = " + myHomePage.filename()); System.out.println("Path = " + myHomePage.path()); }}
程序输出:Extension = htmlFilename = indexPath = /home/mem
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
比较字符串和字符串缓冲区
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
操作字符串
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
修改字符串缓冲区
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
数字类
Number类及其子类主要用于处理数字Number类的对象包含了原始类型的数值并且提供了一些有用的变量和方法,用于对数值进行处理
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
类型包装器类( Type-Wrapper class)
数字类、 Boolean、 Character和void类统称为类型包装器类 在需要对象的地方,可将原始类型的值存储在类型包装器对象中
这些类定义了一些有用的变量,提供关于数据类型的一般信息
这些类还定义了一些有用的方法,用于将值转换为其他类型、转换为字符串等等
这些类用于反射,反射这种 java机制允许程序收集关于 JVM中任何对象或类的信息
此外, BigInteger和 BigDecimal还扩展了原始数据类型
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例程
public class NumberDemo { public static void main(String args[]) { Float floatOne = new Float(14.78f - 13.78f); Float floatTwo = Float.valueOf("1.0"); Double doubleOne = new Double(1.0); int difference = floatOne.compareTo(floatTwo); if (difference == 0) { System.out.println("floatOne is equal to floatTwo."); } else if (difference < 0) { System.out.println("floatOne is less than floatTwo."); } else if (difference > 0) { System.out.println("floatOne is greater than floatTwo."); } System.out.println("floatOne is “ +((floatOne.equals(doubleOne)) ? "equal" : "not equal") + " to doubleOne."); } }
floatOne is equal to oneAgain.
floatOne is not equal to doubleOne.
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
数字的转换、格式化、高级算术功能
自学!
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
数组
数组是一个固定长度的结构,它存储多个相同类型的值数组直接被 JAVA语言所支持,所以没有一个数组类 数组的长度在数组创建的时候就已经确定。数组元素就是数组中的一个数值,可以通过数组中的位置来访问它。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
创建数组
声明一个引用变量来引用一个数组 格式: type[] 引用变量名
type 引用变量名 [] (允许但不推荐) 数组变量的声明并不创建数组
创建一个数组 使用 new操作符显示地创建数组 格式: new elementType[arraySize]
数组初始化器 可以使用简写的语法创建并初始化数组:
type[] 引用变量名 = { …数组元素值 };
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
使用数组
访问数组元素 引用变量名(数组名) [index]
得到数组大小 引用变量名(数组名) .length
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例程
public class ArrayDemo { public static void main(String[] args) { int[] anArray; anArray = new int[10]; for (int i = 0; i < anArray.length; i++) { anArray[i] = i; System.out.print(anArray[i] + " "); } System.out.println(); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
对象数组
数组元素可以是基本类型也可以是引用类型当数组元素是引用类型时(也即数组元素为对象时需要注意:数组元素也必须要被创建和初始化
Integer[] anArray = new Integer[5];
for (int i = 0; i < anArray.length; i++){
System.out.println(anArray[i]);
}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
数组的数组
“ ”数组的数组可以看作是 数组引用 的数组与对象数组一样,必须显示地在数组中创建子数组
子数组的长度并不相同 例: int[ ][ ] aMatrix = new int[4][ ];
…… aMatrix[1] = new int[5]; aMatrix[2] = new int[10];
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
复制数组
public static void arraycopy(Object source, int srcIndex, Object dest,
int destIndex, int length)
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例程
public class ArrayCopyDemo { public static void main(String[] args) { char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
'i', 'n', 'a', 't', 'e', 'd' }; char[] copyTo = new char[7];
System.arraycopy(copyFrom, 2, copyTo, 0, 7); System.out.println(new String(copyTo)); }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
public class WhatHappens { public static void main(String[] args) { StringBuffer[] stringBuffers = new StringBuffer[10]; for (int i = 0; i < stringBuffers.length; i ++){ stringBuffers[i].append("StringBuffer at index " + i); } } }
欢迎提问
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
主要内容提要
创建和使用包
编写和使用接口
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java接口的引入
Java语言只支持单重继承 ,它的程序中的类的层次结构是树状结构 ,在处理复杂问题时单重继承显得力不从心。
为了使 Java程序的类层次结构更加合理,更符合实际问题的需要,我们把用于完成特定功能的若干属性组织成相对独立的属性集合,这种属性的集合就是接口。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java接口定义
定义:接口是一个有名称的方法定义和常量定义的集合 ,但没有方法的实现。
接口定义了一个行为协议 ,类层次结构中任何地方的任何类都可以实现 .
接口是由常量和抽象方法组成的特殊类: 接口中的属性都是用 final修饰的常量 接口中的方法都是用 abstract修饰的没有方法体的抽象方法。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java语言的接口
接口功能的真正实现是由实现接口的各个类来定义接口中各个抽象方法的具体方法体。
Java语言通过接口实现了类间的多重继承功能。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java接口实现多重继承
单一继承指明了子类和父类的层次关系和各自 的行为。多重继承是指一个类有多个父类,这使得类的 层次关系不清楚。 接口则把方法的定义同类的层次区分开来,通 过接口可以在运行中动态地定位所调用的方 法,同时一个类可以实现多个接口,使得接口 提供了比多重继承更简单、更灵活的功能。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
接口 vs 抽象类接口不可以实现任何方法,而抽象类可
以;类可以实现多个接口,但父类仅只有一个;
接口和继承无关 ,不是类层次结构的一部分。无关的类可以实现相同接口。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
定义接口
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
完整的接口定义规范
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
接口定义
接口包括接口声明和接口体两部分:[public] interface 接口名 [extends 父接口名列表 ] { [public][static][final] 类型 变量名 = 常量值; [public][abstract][native] 返回值类型 方法名 (参数列表 ) [throws 异常列表 ];}public interface MyInterface {
int MAXSIZE = 1024; public abstract myMethod(String name);}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
接口定义的说明
声明接口的关键字 interface引导着所定义的接口名字 (符合 Java标识符规定 );
声明接口也需要给出访问控制符 ;接口具有继承性 ,通过关键字 extends声明该新接口是某父接口的派生接口 ;一个接口可以有多个父接口,它们之间用逗号分隔,形成父接口列表。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
接口体的说明
接口体的定义有两个部分 : 对接口中属性的声明 对接口中方法的声明 ;
系统默认 :接口中的所有属性都是 public ,static和 final (公共,静态和最终 );
系统默认 :接口中的所有方法都是 public 和abstract (公共和抽象 );
接口中方法的方法体可用 Java语言书写 ,也可用其它语言书写 (加 native修饰 )。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实例
定义一个股票监视器。一旦股票价格变化,立即通知观察者 watcher。
Watcher是一个接口,它只有一个方法, valueChanged知道股票变化的类必须实现此方法。从而必须实现 StockWatcher接口
不仅仅是 StockMointer的超类,其它类只要实现此接口,就可以享受股票价格变化通知服务。
public class StockMonitor { public void watchStock(StockWatcher watcher, String tickerSymbol, double delta) { } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实现接口
具体地实现接口所规定的功能 , 需要某个类为接口中的所有抽象方法编写实在的方法体。
在类的声明(定义)中用 implements关键字说明该类将要实现哪些接口 ;
如果实现某个接口的类不是 abstract的抽象类,则在类的定义部分必须为所有抽象方法定义具体方法体,方法头部分应该与接口中的定义完全一致 ;
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实现接口
如果实现某接口的类是 abstract的抽象类 ,则在类的定义部分可以不具体实现接口中的所有方法 ;
一个类在实现某个接口的抽象方法时,必须使用完全相同的方法声明。
接口的抽象方法访问修饰符为 public,所以 ,类在实现方法时必须使用修饰符public,否则,系统将警告 ;因为缩小了接口中定义的方法的访问控制范围。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实例
public class StockApplet extends Applet implements StockWatcher {
... public void valueChanged(String tickerSymbol, double
newValue) { if (tickerSymbol.equals(sunTicker)) { ... } else if (tickerSymbol.equals(oracleTicker)) { ... } else if (tickerSymbol.equals(ciscoTicker)) { ...}}}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
接口功能不能简单扩大
例如:要加个报股价的方法在接口里,此时所有实现它的类不能正常工作。
public interface StockWatcher { final String sunTicker = "SUNW"; final String oracleTicker = "ORCL"; final String ciscoTicker = "CSCO"; void valueChanged(String tickerSymbol, double newValue); void currentValue(String tickerSymbol, double newValue); }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
用继承来扩大接口
如果需要增加接口的功能,可以利用继承来实现:
public interface StockTracker extends StockWatcher { void currentValue(String tickerSymbol, double newValue); }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
实现 java.util.Iterator接口的类必须实现哪些方法? Next, hasnext and remove
下面的接口有什么错误?
public interface SomethingIsWrong { public void aMethod(int aValue) { System.out.println("Hi Mom"); }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
如何更正上面接口的错误?
下面的接口是正确的吗?
public interface Marker {}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java语言的包 引入的原因:
容易找到和使用类 避免名称冲突 控制访问
定义:包是一个相关的类和接口的集合 ,它可以提供访问保护和名称空间管理。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java语言的包Java平台中的类和接口是各种包的成员,这些类和接口是按照功能绑定的;
例如:基本的类在 java.lang中;再例如:用于输入和输出的类在 java.io中。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java语言的包
包是一种松散的类的集合 ,通常把需要在一起工作的类 (互相访问 )放入一个包。在 Java语言程序设计中,通常需要定
“ ”义许多类;就像利用 文件夹 把许多文件组织在一起,使硬盘管理的文件更清晰、更有条理一样; Java “ ”利用 包 把一些需要在一起操作的类组织在一起,以便程序员更好地管理操作这些类。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
无名包
“ ”系统自动建立 无名包 ,也就是默认包或缺省包
在缺省情况下 ,系统会为每一个 (.java)源文件创建一个无名 (no name)包 ,这个源文件中定义的所有类都隶属于这个无名包 , 它们之间可以相互引用非 private(私有 )的域或方法;
无名包中的类不能被其它包中的类所引用或复用。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
无名包
缺省包一般只用于临时程序或测试程序 .建议在实际系统开发中,为每个类指定有名的
包。Java使用文件系统来存储包,包的名称必须和程序文件所在目录名完全一样(大小写敏感)。
如果定义了一个多级结构的包,其结构也必须 和文件系统的目录结构完全一致。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
有名包
创建有名包的语句格式为 package <包名 >; 语句功能:该语句将创建一个具有指定名字的包,该包将把当前 .java文件中的所有类集合到这个包内。
创建有名包,应该先创建一个子文件夹(同包名 )以便存放当前 .java文件和对应的 .class文件。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
有名包
例如: package cardclasses; 该语句是将当前类置于包 cardclassess中,需要在当前文件夹下创建一个名为cardclasses的子文件夹。再例如: package cardsystem.cardclasses; 该语句将当前类置于cardsystem.cardclasses中,需要在当前文件夹下创建子文件 cardsystem 并在cardsystem下再创建的子文件cardclasses,当前类存放在这个文件夹里。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
使用包成员
只有公共的包成员可以从定义它们的包外访问,要从包外访问公共的包成员,必须采用以下的方法: 用成员的限定名引用; 导入包成员; 导入成员所属的整个包。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
使用包成员
使用包名作为类名前缀 : java.util.Vector vc = new java.util.Vector() 加载需要使用的类 import java.util.Vector; …… Vector vc = new Vector();
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
使用包成员
加载整个包 import java.util.*; …… Vector vc = new Vector();消除名称的二义性
使用成员的限定名; 使用环境变量 classpath
set classpath=…… javac –classpath …… MyClass.java java –classpath …… MyClass
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
使用包成员
在使用 import语句的时候,可以使用通配符一次导入一个包中的所有类,如:
import java.util.*;这样,我们在使用 java.util包中的任何类时,就可以直接使用简单类名。需要注意的是, import语句要么导入一个类,要么导入一个完整包。不能使用通配符标记包的子集或多个包,下面三条语句均无法通过编译:
import java.applet.A*; import java.*.*; import java.*.io;
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
使用包成员
为了简化代码, Java语言规定在以下情况时无需使用 import语句导入包: 使用缺省包中的类 使用 java.lang包中的类 使用和当前类在同一个包中的其他类
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
管理源代码文件
将类或者接口的源代码放在一个文本文件中,文件名为类或者接口的简单名;
将源代码文件放在一个目录中,目录名反映的是类或者接口所属的包的名称。
例如:
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
管理源代码文件
包成员的限定名称与文件的路径是对应的,它们的对应关系为:
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
管理类文件
与源代码文件一样,字节码文件也可以通过包来进行管理;
字节码文件不必和源代码文件位与相同的目录中,可以单独管理;这样做的目的可以隐藏源代码文件。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
类路径
定义:类路径是一个目录或 zip文件的有序列表,用于搜索类文件。
类路径中列出的每个目录都是包含包目录的顶层目录,编译器和解释器可以根据类的包名称和类名从顶层目录开始构造路径的其余部分。
例如:上图所示的目录结构的类路径项目包含 classes,但是不包含 com或者 com以下的任何目录,编译器和解释器用 .class文件的完整包名构造它的路径名。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
假设你已经写了一些类,并且需要将这些类放进三个包中,如下所示:
为了将这些类放到正确的包中,需要在每个源代码中增加什么代码?
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
In Client.java add: package mygame.client;
In Server.java add: package mygame.server;:
In Utilities.java add: package mygame.shared;
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
“ ”为了遵守 管理源代码文件和类文件 所述的目录结构,需要在开发目录下创建一些子目录,并且将源代码文件放到正确的子目录中,必须创建哪些子目录?各个源代码文件应该放在哪个子目录中?
In mygame/client/ place: Client.java In mygame/server/ place: Server.java In mygame/shared/ place: Utilities.java
欢迎提问
第 7 章 异常处理华中科技大学 IBM技术中心
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
为什么要异常处理?
对于任何语言的程序设计而言,错误的发生总是不可避免的
为了加强程序的健壮性,程序设计时,必须充分考虑错误发生的可能性,并建立相应的处理机制。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
什么是异常?
异常( Exception)又称为例外,是指在程序运行过程中发生的非正常事件,这些事件的发生会影响程序的正常执行。如: “ ”进行数学中 无意义 的运算,例如除数为零、对负数求对数平方根等
对数组进行操作时,超出了数组的最大下标 程序所需进行的 I/O操作不能正常执行,如所需访问的文件不存在
内存耗尽无法进行类的实例化 JVM崩溃
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
异常对象
在 Java语言中,我们用异常对象来表示不同的异常。
所谓 Java异常对象就是一个存放着相关错误信息的对象,如果方法运行时产生了异常,该方法就可以抛出一个异常对象
为了表示不同种类的异常, Java语言中定义了许多异常类。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
方法的调用堆栈
main()
methodA()
methodB()
methodC() 调用
Java程序在执行的过程中,形成了一个先进后出的调用堆栈,各方法之间依照调用先后的不同,由先至后的进入调用堆栈,堆栈的最上层即是当前被调用执行的方法。该方法执行完毕后,会将
处理器控制权交还给调用他的方法,依此类推。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
方法调用堆栈中异常对象的传递
当某一方法中的一个语句抛出一个异常时,如果该方法中没有处理该异常的语句,那么该方法就会中止执行,并将这个异常传递给堆栈中的下一层方法,直到某一方法中含有处理该异常的语句为止。如果该异常被传递至主方法,而主方法中仍然没有处理该异常的语句,则异常将会被抛至 JVM,程序中断。
main()
methodA()
methodB()
methodC() 调用
传
递
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例 程public class ExampleOfException { String[] lines = {"The first line", "The second line","The last line"}; public static void main (String[] args) { ExampleOfException eoe = new ExampleOfException(); eoe.methodA(); System.out.println("Program finished."); } void methodA() { methodB(); } void methodB() { methodC(); } void methodC() { for (int i=0; i<4; i++) System.out.println (lines[i]); }}
The first lineThe second lineThe last lineException in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at ExampleOfException.methodC(ExampleOfException.java:16) at ExampleOfException.methodB(ExampleOfException.java:12) at ExampleOfException.methodA(ExampleOfException.java:9) at ExampleOfException.main(ExampleOfException.java:6)
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java中的异常类
在 Java语言中,任何的异常对象都是 Throwable类的直接子类或间接子类的实例。 Java的类库已经提供了一些常见的异常类,如果这些异常类不能够
满足要求,用户也可以创建自己的异常类。
Throwable
Exception
RuntimeException IOException
NullPointerException ArithmeticException …… FileNotFoundException
……
……
Error
VirtualMachineError ……
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Exception类
Exception的子类表示了不同类型的异常,例如 RuntimeException表示运行时异常,而 IOException表示 I/O问题引起的异常。
这些子类也可以被继承以对不同类型的异常进行细分,如 RuntimeException还可细分为NullPointerException、 ArithmeticException等; IOException还可细分为FileNotFoundException、 EOFException等。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
常见的异常类
ArithmeticExceptionArrayIndexOutOfBandsExceptionIOExceptionFileNotFoundExceptionNullPointerExceptionNumberFormatException
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Error类
Error类表示 Java运行时产生的系统内部错误或资源耗尽等严重错误。
这种错误通常是程序无法控制和解决的,如果发生这种错误,通常的做法是通知用户并中止程序的执行。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
常见的错误类
NoClassDefFoundErrorOutOfMemoryErrorVirtualMachineError
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
必检异常与非必检异常
RuntimeException类及其子类被称“ ”为 运行时异常
一般发生在 JRE内部 “ ”也称 非必检异常 如 NullPointerException
“ ”其他异常被成为 非运行时异常 一般发生在 JRE外部 “ ”也称 必检异常 如 IOException
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
异常处理的一般步骤
异常抛出
异常捕获
异常处理
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
抛出异常
方法中需要抛出异常时,可使用 throw语句实现,具体步骤应该是: 选择合适的异常类; 创建该类的一个对象; 使用 throw语句抛出该对象。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
抛出异常
例如,某方法 readFile()对文件进行读操作,根据前面章节的介绍可以知道:当进行 I/O操作时,可能会产生 I/O异常。所以,在方法readFile中如果读文件操作不成功,则应抛出I/O异常。如下列程序片断所示:
readFile() throws IOException{ … if (读文件不成功 )
throw new IOExcepion();}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
抛出异常
如果一个方法可能抛出多个必检异常,那么必须在方法的声明部分一一列出,多个异常间使用逗号进行分隔:
Class MyClass {…
public myMethod(String s) throws IOException, MalformedURLException { … } …}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
抛出异常
一个方法必须通过 throws语句在方法的声明部分说明它可能抛出而并未捕获的所
“ ”有的 必检异常 ,如果没有这么做,将不能通过编译。
值得注意的是:如果在子类中覆盖了父类的某一方法,那么该子类方法不可以比被其覆盖的父类方法抛出更多的异常(但可以更少)。所以,如果被覆盖父类的方法
“ ”没有抛出任何的 必检异常 ,那么子类方“ ”法绝不可能抛出 必检异常 。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
抛出异常
在下面的例子里,对于父类 SuperClass而言,类 SubClassA是正确的子类,而SubClassB 则是错误的。
class SuperClass{public superMethod() throws EOFException {
…}
}class SubClassA extends SuperClass{ //正确
public superMethod() {…
}}class SubClassB extends SuperClass{ //错误
public superMethod() throws FileNotFoundException{…
}}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
异常的捕获
要捕获一个异常,程序员只需要在程序中设置一个 try/catch块,其格式如下:
try{ 抛出异常的代码 }catch (某 Exception 类型 e){ 处理该异常类型的代码 }catch (某 Exception 类型 e){ 处理该异常类型的代码 }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
异常的捕获
当 try块中的某条代码抛出异常时:首先,自该语句的下一条语句起的所有 try块中的剩余语句将被跳过不予执行;其次,程序执行 catch子句进行异常捕获,异常捕获的目的是进行异常类型的匹配,并执行与所抛出的异常类型相对应的catch子句中的异常处理代码。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
异常的捕获
需要注意的是:如果 try块中没有任何的异常抛出,则所有的 catch子句将会被跳过;如果 try块中所抛出的异常对象类型与所有的 catch子句中的所声明的异常类型都不匹配,则方法会立即中止,并将该异常对象继续抛出,沿调用堆栈传递。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
example
public class ExampleOfException { String[] lines = {"The first line", "The second line","The last line"}; public static void main (String[] args) { ExampleOfException eoe = new ExampleOfException(); eoe.methodA(); System.out.println("Program finished."); } ... void methodC() { for (int i=0; i<4; i++) { try { System.out.println (lines[i]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Re-setting Index Value"); } } }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
example上面的例子中可能会产生数组越界异常,所以将其置于 try块中,并在 catch子句中对ArrayIndexOutOfBoundsException类型的异常进行捕获,并进行处理。
如果 try块中可能抛出多个类型的异常,程序员可以使用多个 catch子句对这些异常进行捕获,每种异常类型对应一个单独的 catch子句。
需要注意的是,这些 catch子句是顺序执行的。这意味着,异常对象总是被第一个 catch子句首先捕获,如果类型不匹配,才会执行下一个catch子句。读者可以试着分析下面的程序片断,看看有什么样的问题存在。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
Java运行系统从上到下分别对每个 catch语句处理的例外类型进行检测 ,直到类型匹配为止;
catch语句的排列顺序应该是从子类到父类
try { …}catch(Exception e) { … }catch(IOException e) { … }catch(ArrayIndexOutOfBoundsException e) { … }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
finally
当一个方法的某条语句抛出异常后,该方法剩余的语句将无法继续执行。这种情况下,方法往往无法将其占用的资源进行释放。
解决方法: 在每个 catch子句的异常处理代码中也加上资源释放的代码,但这种方法非常麻烦;
Java语言的异常处理机制中提供了一个更好的方案-程序员可以使用 finally子句来统
一进行资源释放之类的工作。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
finally
finally子句的一般格式: try{
抛出异常的代码 }catch (某 Exception 类型 e){
处理该异常类型的代码 }
… }catch (某 Exception 类型 e){
处理该异常类型的代码 }finally{
最后一定会被执行的代码 }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
finally
不论 try块中的代码是否抛出异常及异常是否被捕获, finally子句中的代码一定会被执行: 如果 try块中没有抛出任何异常,当 try块中的代码执行结束后, finally中的代码将会被执行;
如果 try块中抛出了一个异常且该异常被 catch正常捕获,那么 try块中自抛出异常的代码之后的所有代码将会被跳过,程序接着执行与抛出异常类型匹配的catch子句中的代码,最后执行 finally子句中的代码。
如果 try块中抛出了一个不能被任何 catch子句捕获(匹配)的异常, try块中剩下的代码将会被跳过,程序接着执行 finally子句中的代码,未被捕获的异常对象继续抛出,沿调用堆栈顺序传递。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
当调用上述方法 m()时, try块中包含方法的 return语句,返回值为 1。然而,实际调用该方法后产生的返回值为 0。这是因为在方法实际返回并结束前, finally子句中的内容无论如何要被执行,所以 finally子句中的 return语句使得该方法最终实际返回值为 0 。
public int m(){ try {
return 1; }finally{
return 0; }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
example
public class TryCatchFinally{ static void Proc( int sel ){ System.out.println("----- In Situation"+sel+" -----"); try{ if( sel==0 ){ System.out.println("no Exception caught"); return; }else if( sel==1 ){ int i=0; int j=4/i; }else if( sel==2 ){ int iArray[]=new int[4]; iArray[10]=3; }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
example
}catch( ArithmeticException e ){ System.out.println("Catch "+e); }catch( ArrayIndexOutOfBoundsException e ){ System.out.println("Catch "+e.getMessage()); }catch( Exception e ){ System.out.println("Will not be executed"); }finally{ System.out.println("in Proc finally"); } } public static void main( String args[] ){ Proc( 0 ); Proc( 1 ); Proc( 2 ); }}
程序运行结果:----- In Situation0 -----no Exception caughtin Proc finally----- In Situation1 -----Catch java.lang.ArithmeticException: / by zeroin Proc finally----- In Situation2 -----Catch 10in Proc finally
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
声明异常
一个方法不处理它产生的异常 ,而是沿着调用堆栈向上传递 ,由调用它的方法来处理这些异常,则需要声明异常。
声明异常的方法: returnType methodName([paramlist]) throws
exceptionList例如: void compute(int x) throws
ArithmeticException{ … }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
example
public class ThrowsException1{ static void Proc(int sel) throws ArrayIndexOutOfBoundsException { System.out.println("-----In Situation"+sel+"-----"); if(sel==0){ System.out.println("no Exception caught"); return; }else if(sel==1){ int iArray[]=new int[4]; iArray[10]=3; } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
example
public static void main(String args[]){ try{ Proc(0); Proc(1); }catch(ArrayIndexOutOfBoundsException e){ System.out.println("Catch "+e); }finally{ System.out.println("in Proc finally"); } }} 程序运行结果:
----- In Situation0 -----no Exception caught----- In Situation1 -----Catch java.lang.ArrayIndexOutOfBoundsException: 10in Proc finally
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
创建自己的异常类
Java语言中允许用户定义自己的异常类,这些用户自定义异常类必须是 Throwable的直接子类或间接子类。
根据 Java异常类的继承关系,用户最好将自己的异常类定义为 Exception的子类,而不要将其定义为 RuntimeException的子类。因为对于 RuntimeException的子类而言,即使调用者不进行处理,编译程序也不会报错。将自定义异常类定义为Exception的子类,可以确保调用者对其进行处理。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
example
class MyException extends Exception{ private int detail; MyException( int a ){ detail = a; } public String toString( ){ return "MyException "+detail; }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
example
public class ExceptionDemo{ static void compute(int a) throws MyException { System.out.println("called compute("+a+")"); if( a>10 ) throw new MyException(a); System.out.println("normal exit"); } public static void main( String args[] ){ try{ compute( 1 ); compute( 20 ); } catch( MyException e ){ System.out.println("Caught "+e); } }}
程序运行结果:called compute(1)normal exitcalled compute(20)Caught MyException 20
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
异常的优点
“ ”将错误处理代码与 常规 代码分离; 例 7.7.1
将错误沿调用堆栈传递; 可以由感兴趣的方法来处理异常
对错误类型进行分组和区分。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
说明的问题
方法也可以不对异常进行捕获而直接将其抛出,并在方法声明中进行说明,那么对方法产生的异常到底是应该直接进行捕获还是应该将其进行传递呢?
一般来说,对于方法的最终调用者而言,他必须捕获并处理该方法抛出的异常。而对于抛出异常的方法而言,应该对方法可能产生的异常进行区分,尽量避免一些异常的产生,捕获并处理那些你知道如何处理的异常,而对那些你不知道方法的调用者会如何处理的异常,最好将它们留给方法的调用者进行处理,这样会增加程序的灵活性。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
说明的问题
需要特别指出的是,虽然异常处理机制为程序员提供了非常大的方便,但是作为一个好的程序员要尽量避免异常的过度使用。这是因为:异常对象的实例化和其后续处理工作是非常消耗资源的,过度的使用异常会明显影响程序的执行速度。所以,在使用异常处理时应该仔细考虑,只对有必要的异常情况使用异常,而不可以
将异常泛化。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
两段代码的比较
代码 1:try { int n = InputReader.inputInteger(请输入一个整数 "); if (n<100 || n>1) throw new NumberFormatException();}catch (NumberFormatException e) {
System.out.println("输入范围错误! ");}
代码 2:int n = InputReader.inputInteger(请输入一个整数 ");if (n<100 || n>1)
System.out.println("输入范围错误! ");
代码 1采用了异常处理方式;代码 2则通过对用户输入的分析避免了异常的使用,提高了代码效率。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
下面的代码合法吗?try {...} finally {...}
下面的代码可以捕获何种异常?使用这种异常处理器有什么问题?catch (Exception e) {...}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题
下面的处理器可以捕获什么异常?} catch (Exception e) {...} catch (ArithmeticException a) {...}这个异常处理器中有错误吗?此代码能否被编译?
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
问题public static void cat(File named) { RandomAccessFile input = null; String line = null; try { input = new RandomAccessFile(named, “r”); while ((line = input.readLine()) != null { System.out.println(line); } return; } finally { if (input != null) { input.close(); } }}
第八章 线程华中科技大学 IBM技术中心
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
主要内容
线程的死锁
线程的同步
线程的生存周期
如何创建线程
线程的基本概念
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
什么是线程
线程是程序内的一个单一的顺序控制流“程,也被称为 轻型进程 (lightweight
process)” “或 执行上下文 (execution context )”
线程用于分隔任务线程类似于传统的顺序程序,都有一个执行的起点,经过一系列指令后到达终点。线程在执行过程中的任何时刻只能有一个执行点
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
几个相关概念
1
“ ”程序 代表一个静态的对象,是内含指令和数据的文件,存储在磁盘或
其他存储设备中
2
“ ”进程 代表一个动态的对象,是程序的一个执行过程,存在于系统的内存中。一个进程对应于一个程序
3
“ ”线程 是运行于某个进程中,用于完成某个具体任务的顺序控制流程,有时被称为轻型进程。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
线程的作用
线程真正的神奇之处并不在于它处理顺序任务流程的作用,而是在于多个线程可以同时运行,并且在一个程序内执行不同的任务
演示排序程序
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
如何创建线程
继承 Thread类
定义线程的方法
实现 Runnable接口
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
继承 Thread类
在构造函数中调用父类的构造函数 参考 Thread类的构造函数
在 run方法中实现任务处理功能创建线程对象后,通过调用 start()方法启动线程
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
继承 Thread类 class PrintThread extends Thread { private int sleepTime; public PrintThread( String name ) { super( name ); sleepTime = (int) ( Math.random() * 5000 ); System.out.println( "Name: " + getName() + "; sleep: " + sleepTime ); } public void run() { try { System.out.println( getName() + " going to sleep" ); Thread.sleep( sleepTime ); } catch ( InterruptedException ie ) { System.err.println( ie.toString() ); } System.out.println( getName() + " done sleeping" ); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
执行线程任务
public class ThreadTester { public static void main( String args[] ) { PrintThread thread1, thread2, thread3, thread4; thread1 = new PrintThread( "thread1" ); thread2 = new PrintThread( "thread2" ); thread3 = new PrintThread( "thread3" ); thread4 = new PrintThread( "thread4" ); System.out.println( "\nStarting threads" ); thread1.start(); thread2.start(); thread3.start(); thread4.start(); System.out.println( "Threads started\n" ); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实现 Runnable接口
实现 run方法,在该方法中实现任务处理功能 参考 Runnable接口定义
创建实现 Runnable接口的类对象利用 Thread类的构造函数创建线程对象
public Thread(Runnable target) 通过调用线程对象的 start()方法启动线程
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
实现 Runnable接口 class PrintRunnable implements Runnable { private int name; private int sleepTime; public PrintRunnable( String name ) { this.name = name; sleepTime = (int) ( Math.random() * 5000 ); System.out.println( "Name: " + name + "; sleep: " + sleepTime ); } public void run() { try { System.out.println( name + " going to sleep" ); Thread.sleep( sleepTime ); } catch ( InterruptedException ie ) { System.err.println( ie.toString() ); } System.out.println( name + " done sleeping" ); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
执行线程任务
public class RunnableTester { public static void main( String args[] ) { PrintRunnable thread1, thread2, thread3, thread4; thread1 = new PrintRunnable ( "thread1" ); thread2 = new PrintRunnable ( "thread2" ); thread3 = new PrintRunnable ( "thread3" ); thread4 = new PrintRunnable ( "thread4" ); System.out.println( "\nStarting threads" ); new Thread(thread1).start(); new Thread(thread2).start(); new Thread(thread3).start(); new Thread(thread4).start(); System.out.println( "Threads started\n" ); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
选择合适的方式创建线程
继承 Thread类 简单直观 不能继承其他父类
实现 Runnable接口 可继承其他父类 代码稍复杂
ClockApplet示例
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
ClockApplet示例
import java.applet.Applet; import java.awt.Graphics; import java.util.Date; public class ClockApplet extends Applet implements Runnable { private Thread clockThread = null; public void start() { if (clockThread ==null) { clockThread = new Thread(this); clockThread.start(); } } public void paint(Graphics g) { Date date = new Date(); g.drawString(date.toString(), 5, 10); }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
ClockApplet示例
public void run() { while (true) { repaint(); try { Thread.sleep(1000); } catch (InterruptedException e) { } } }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
线程的生存周期
创建 消亡运行
阻塞
就绪
休眠
等待
start()
sleep()
wait()
I/O
CPU可用 任务完成
yield()
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
线程状态的转换条件
可运行状态和不可运行状态转换条件
进入不可运行状态条件 返回可运行状态条件挂起(调用 suspend()方法) 调用 resume()方法
睡眠(调用 sleep()方法) sleep()方法的指定时间结束
阻塞(请求 I/O操作) I/O操作结束
等待(调用某对象的 wait()方法) 调用该对象的 notfiy()或 notifyAll()方法
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
停止线程
正常终止 run()方法运行完毕
强行中止 调用线程对象的 stop()方法 创建线程对象的上级线程停止
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
线程的优先级
Java线程优先级 范围从 1- 10,数字越高越能被优先执行 通过线程对象的 setPriority()方法设置优先级 缺省优先级为 5 三个常数:
MAX_PRIORITY、MIN_PRIORITY、 NORM_PRIORITY
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
线程的调度
大多数计算机只有一个 CPU,因此一个时刻只“有一个线程在运行,多个线程只能是 宏观上并
”行,微观上串行在有限个 CPU的系统中确定多个线程的执行顺序称为线程的调度
Java “语言采用了简单的 固定优先级调度算”法 ,高优先级的线程总是更容易得到 CPU使用权。
只有当所有高优先级的线程停止或处于不可运行状态,低优先级的线程才能运行。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
抢占式调度
Java “ ”语言的 抢占式调度策略 当一个线程正在运行时,如果有更高优先级的线程处
“ ”于 可运行 状态,系统将强制暂停低优先级的线程,“ ”使高优先级的线程 抢占 低优先级线程的 CPU资源
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
自私的线程
线程如果不放弃 CPU,其他同优先级的线程就很难得到运行
run() {while(true) {……// yield();}
}除非更高优先级的抢占 CPU ……,或者
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
时间片策略
部分平台(如Windows “ ”)针对 自私线程 采用 了时间片轮换策略
将 CPU的运行时间划分成段,相同优先级的线程分别占用一段轮流执行
执行的顺序和轮换的时间不可预测
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
正确理解优先级和调度
线程调度策略和 JRE运行平台直接相关 Java本身并不直接支持时间片
“ ”不要编写 自私的 线程 在适当的时候通过 yield()方法放弃 CPU yield()方法使线程由运行状态变为就绪状态 yield()方法放弃 CPU后,只有同优先级的线程才能得到 CPU,低优先级的线程仍不能运行
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
正确理解优先级和调度
在多任务环境中,如果完全依赖低优先级线程可“ ” 能永远得不到运行机会,称为线程 饿死
线程调度程序可能为低优先级线程分配 CPU,以防“ ”止线程 饿死
优先级只是用来提高多线程的调度效率,并不保证高优先级线程永远优先运行 不要依赖线程的优先级来设计对调度敏感的算法
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
正确理解优先级和调度
public class PriorityTest extends Thread { public PriorityTest(String name) { super(name); } public void run() { while(true) { int i; for(int j=0; j<100000; j++) for(int k=0; k<1000; k++) i = j + k; if (getPriority()<NORM_PRIORITY) System.out.println(getName() + " is running."); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
正确理解优先级和调度
public static void main(String[] args) { PriorityTest test1 = new PriorityTest("Higer priority thread"); PriorityTest test2 = new PriorityTest("Lower priority thread"); test2.setPriority(4); test1.start(); test2.start(); } }
从运行结果上看,低优先级的线程也有执行的机会。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
线程的调度
当多个线程对同一个对象进行读写操作的时候,如果完全不加控制,可能会出现难以预料的结果
“比较典型的是 生产者 / ”消费者 问题 一个线程(生产者)修改数据 另一个线程(消费者)读取数据 希望生产者每次修改的数据都能被消费者读取,并且不会重复读取
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
生产者 /消费者问题
涉及 4个对象 CubbyHole对象,用于保存生产者的修改,并能让消费者读取
Producer对象,产生 0-9,存入 CubbyHole对象中 Consumer对象,读取 CubbyHole对象中的数据 ProdConsTester,测试运行程序
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
生产者 /消费者问题
CubbyHole类 public class CubbyHole { private int data; public int get() { return this.data; } public void put(int data) { this.data = data; } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
生产者 /消费者问题 Producer类
public class Producer extends Thread { private CubbyHole res; public Producer(CubbyHole res) { this.res = res; } public void run() { for (int i=0; i<10; i++) { res.put(i); System.out.println(“Producer put:” + i); try { sleep((int)(Math.random()*100)); } catch (InterruptedException e) { } } } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
生产者 /消费者问题
Consumer类 public class Consumer extends Thread { private CubbyHole res; public Consumer(CubbyHole res) { this.res = res; } public void run() { for (int i=0; i<10; i++) { System.out.println(“Consumer get:” + res.get()); try { sleep((int)(Math.random()*100)); } catch (InterruptedException e) { } } } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
生产者 /消费者问题
ProdConsTester类 public class ProdConsTest { public static void main(String[] args) { CubbyHole res = new CubbyHole(); Producer pro = new Producer(res); Consumer con = new Consumer(res); pro.start(); con.start(); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
生产者 /消费者问题
分析运行结果可发现两个问题 生产者产生的资源可能没有被消费者获取 生产者产生的资源可能被消费者重复取得
造成这些问题的原因是两个线程在访问同一个对象时没有考虑同步的控制。 当消费者尚未取得资源时,生产者可能已经产生新的资
源,使消费者错过一些资源 当生产者尚未产生新资源时,消费者再次执行 get()方法,
造成资源被重复获取
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
引入同步机制
解决前述问题的关键是引入线程之间的同步控制逻辑
通过 synchronized关键字锁定共享对象 方法名前加 synchronized关键字标记 用 synchronized(Object) {…}标记锁定的代码
当线程执行由 synchronized关键字控制的代码时,就锁定了共享对象。其他线程如果需要操作该对象,就必须等待该线程执行完受保护的代码
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
新的 CubbyHole public class CubbyHole { private int data; private boolean getable; public synchronized int get() { while (getable == false) { try { wait(); } catch (InterruptedException e) { } } getable = false; notifyAll(); return this.data; }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
新的 CubbyHole public synchronized void put(int data) { while (getable == true) { try { wait(); } catch (InterruptedException e) { } } this.data = data; getable = true; notifyAll(); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
更新后的运行结果
Producer put:0 Consumer get:0 Producer put:1 Consumer get:1 Producer put:2 Consumer get:2 Consumer get:3 Producer put:3 Producer put:4 Consumer get:4 Consumer get:5 Producer put:5 Producer put:6 Consumer get:6 Consumer get:7 Producer put:7 Producer put:8 Consumer get:8 Producer put:9 Consumer get:9
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
线程的死锁
synchronized关键字可以解决多线程同步问题,但——如果处理不当,可能产生新的问题 死锁
当多个线程分别占用某个资源,并等待其他线程释放该资源时,可能产生死锁
synchronized a() {… b();}synchronized b() {… a();}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
线程的死锁
任何程序员在处理并发线程竞争资源的时候,都必须仔细考虑如何避免死锁 不要设计功能过于复杂,执行时间过长的线程 不要设计过多线程 编写可以检测死锁的代码
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
线程的分组
线程组可以将多个线程集中在一个对象中,并同时 操作这些线程(比如全部挂起或杀死)
所有的 Java线程都是某个线程组的一员。当 Java应用程序开始执行时,虚拟机会创建一个名为main的线程组
如果程序没有显示地创建其他线程组并将线程设置其中,则所有的线程都是main 线程组的成员
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
创建线程组
可利用 ThreadGroup类创建线程组对象
ThreadGroup myGroup = new ThreadGroup(“my group”);
Thread thread1 = new Thread(myGroup, “thread one”);
Thread thread2 = new Thread(myGroup, “thread two”);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
使用线程组
使用线程组对象操作多个线程: public int activeCount() 返回线程组中活动线程的估计数 public final void stop() 停止线程组中的所有线程 public final void suspend() 挂起线程组中的所有线程 public final void resume() 唤醒线程组中所有被挂起的线程 public final void setMaxPriority(int pri) 设置线程组的最大优先级,组中的线程优先级不得高于该值
欢迎提问
第 9 章 I/O:读和写华中科技大学 IBM技术中心
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
I/O与流I/O是程序设计中的重要问题,大部分的应用程序都需要 I/O操作,比如从键盘获得用户输入、在屏幕输出运行结果、对磁盘文件进行读写等等。应用程序只有通过 I/O操作才能实现与用户的交互及数据的处理及
存储在 Java语言中,将不同类型的 I/O抽象
“为流。所谓 流( stream ”) ,可以看作 是数据在文件或程序之间的传递
数据源 程序据
流
数
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
输入流和输出流
一般来说,流有两种基本形式:输入流和输出流,根据程序是作为数据流的目的端还是源端来划分。程序首先要打开一个
流,才能与数据文件进行通信。通过输入流,程序可以从数据文件读取数据,但不可向输入流中写入数据;反之,通过输出流,程序可以向数据文件中写入数据。程序与其他设备间的 I/O也可以使用流,这时可将设备看作是一个数据文件。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Java I/O流类的组织模式
输 出 流 输 出 流 抽 象 类
文件
缓冲区
管 道
介质
输 入 流 抽 象 类 输 入 流
与介质相关的类
低层次界面
高层次界面
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
java.io在 Java开发环境中,主要是由包 java.io中提供的一系列的类和接口来实现输入 /输出处理。而标准输入 /输出处理则是由包 java.lang中提供的类来处理的,这些类又都是从包 java.io中的类继承而来的。
I/O类提供了低层次和高层次的界面。每一种介质都有一对与之相关联的输入输出类,它们提供低层次的面向数据序列(字符、字节)的界面。与介质相关的各个类都分别是输入输出抽象流类的子类,它们通常具有与介质相关的构造器及方法。
I/O抽象类为所有与介质相关的具体输入输出类提供了一个统一的界面。反过来各个具体的与介质相关的输入输出类也扩展了抽象类,通过它们可以实现在具体介质上的输
入输出操作
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
I/O操作的一般步骤
构造一个与介质相关的 I/O对象,以提供一种低层次的方法将数据输入或输出到相应的介质;
将与介质相关的对象强制类型转换为它的父类(即抽象 I/O类),并利用该对象构造一个流对象。这样便建立起了流类对象与介质相关对象的关联;
这时就可利用流对象的 I/O方法进行相应介质上的数据读写。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
字节流类
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
InputStream类InputStream类定义了一套所有字节输入流
所需的方法方法 描述
read() 将数据读入流中
skip() 跳过流中的若干字节
available() 返回当前流中的可用字节
mark() 在流中标记一个位置
reset() 返回到流中的标记位置
markSupported()
返回一个 boolean值,描述流是否支持标记和复位
close() 关闭流
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
OutputStream类
OutputStream类定义了一套所有字节输 出流所需的方法。
方法 描述
write() 写数据到流
flush() 强制将被缓冲的内容写到输出
close() 关闭流
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
字符流类
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Reader与Writer类 Reader类的相关方法:
void close() void mark(int readAheadLimit) boolean markSupported() int read() int read(char[] cbuf) int read(char[] cbuf, int off, int len) boolean ready() void reset() long skip(long n)
Writer类的相关方法: void close() void flush() void write(char[] cbuf) void write(char[] cbuf, int off, int len) void write(int c) void write(String str) void write(String str, int off, int len)
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
流的使用( 1)I/O类型 流 作用
内存
CharArrayReaderCharArrayWriterByteArrayInputStreamByteArrayOutputStream
用来从内存读取数据或向内存写入数据
StringReaderStringWriterStringBufferInputStream
从内存里的某个 String或 StringBuffer读字符或字节
管道
PipedReaderPipedWriterPipedInputStreamPipedOutputStream
实现一个输入、输出管道。管道可用于一个线程的输出连接到另一个线程的输入
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
流的使用( 2)
文件
FileReaderFileWriterFileInputStreamFileOutputStream
用于对本机文件系统上的一个件行读写
联结 N/ASequenceInputStream
将多个输入流联结成为一个输入流
对象串行化N/AObjectInputStreamObjectOutputStream
将对象串行化
数据转换N/A DataInputStreamDataOutputStream
以一种与机器无关的格式读写原始数据类型
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
流的使用( 3)
计数LineNumberReaderLineNumberInputStream
在读取时记录行数
预览 PushbackReaderPushbackInputStream “带有 回推 (pushback)”缓冲区的输入流
打印 PrintWriterPrintStream 包含便捷的打印方法的流。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
流的使用( 4)
缓冲
BufferedReaderBufferedWriterBufferedInputStreamBufferedOutputStream
缓冲流,用于在读写时进行数据缓冲
过滤
FilterReaderFilterWriterFilterInputStreamFilterOutputStream
过滤流的抽象类接口。数据读写时对数据进行过滤
在字节和字符之间转换
InputStreamReaderOutputStreamWriter 字节流和字符类间的转换桥梁
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
文件流
要对本机文件系统上的文件进行读写,需要使用文件流。 Java的文件流类包括字符流的 FileReader、 FileWriter和字节流的FileInputStream、 FileOutputStream。文件流对象的构造需要提供文件名作为参数,也即可以通过文件名来创建文件流。这里的所谓文件名可以是字符串、 File对象或 FileDescriptor对象。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例程
import java.io.*;class Copy{ private void copy(InputStream in, OutputStream out) throws IOException { byte[] buf = new byte[4096]; int len = in.read(buf); while (len != -1) { out.write(buf, 0, len); len = in.read(buf); } } public void cat(String fsrc, String fdest) { try { InputStream in = new FileInputStream(fsrc); OutputStream out = new FileOutputStream(fdest, true); copy(in, out); out.close(); in.close(); }catch (IOException ex) { System.err.println(ex);} }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例程 -cont.public class UseCopy{
public static void main(String[] args){Copy c=new Copy();c.cat(“in.dat”,”out.dat”);
}}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
内存流
为了支持内存上的输入输出, java.io包内提供了一组相关的类: 字节流类—— ByteArrayInputStream
ByteArrayOutputStream StringBufferInputStream
字符流类—— CharArrayReader CharArrayWriter StringReader StringWriter
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例程
import java.io.*;public class ByteArrayOutputStreamTest { public static void main(String[] args) {
try{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); for (int i = 0; i < 1000; i++){
ps.println(i + " ABCDEFGHIJKLMNOPQRSTUVWXYZ"); } long start = System.currentTimeMillis();
FileOutputStream fos = new FileOutputStream("ByteArrayOutputStreamTest");
baos.writeTo(fos); fos.close();
long stop = System.currentTimeMillis(); System.out.println("time elapsed (milliseconds) = " + (stop - start)); }catch (FileNotFoundException fnfe) {
System.out.println(fnfe.getMessage()); }catch (IOException ioe) { System.out.println(ioe.getMessage()); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
管道流
管道是用来把一个线程的输出连接到另一个线程的输入。管道输入流作为一个通信管道的接收端,管道输出流则作为发送端。管道流必须是输入输出并用,也就是说在使用管道前,两者必须进行连接。
输出流 ( pi pe)管道 输入流
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
为什么要用到管道流?
当某个程序的输出作为另外一个程序的输入时,如果没有管道,就必须为程序提供一个存放中间结果的位置,前一个程序将输出数据写入该位置,而后一个程序再从该位置读出这些数据,这样的做法无疑是低效率的。
通过管道,可以连接程序的输出和输入,直接将前一程序的输出作为后一程序的输入,提高了程序效率。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
管道流的连接方式
java.io中为字符类型和字节类型各提供了一对输入输出管道流类: PipedReader/ PipedWriter和 PipedInputStream/PipedOutputStream。
管道流的连接方式有两种,以PipedInputStream/PipedOutputStream为例: 在构造方法中进行连接:PipedInputStream(PipedOutputStream pos);
PipedOutputStream(PipedInputStream pis); 通过各自的 connect()方法连接:
在类 PipedInputStream中, connect(PipedOutputStream pos);
在类 PipedOutputStream中, connect(PipedInputStream pis);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例程
class PipedExample { public static void main(String args[]) throws IOException{ byte dataA = 123, dataB= 321; PipedInputStream pis = new PipedInputStream(); PipedOutputStream pos = new PipedOutputStream(pis); System.out.println("PipedInputStream"); try{ pos.write(dataA);
pos.write(dataB); System.out.println((byte)pis.read()); System.out.println((byte)pis.read());
}finally{ pis.close(); pos.close(); } }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
过滤器流
在某些情况下,对于由程序写入或读取的数据, 需要在写入或读取之前对其进行处理或者过滤
总的来说,过滤器的作用是对相关输入输出流中的数据进行处理,而对于程序而言,这些过滤器是透明的。
介 质介 质
输出流
输入流
过滤器
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
过滤器流类
类型 类 作用
字节
FilterInputStreamFilterOutputStream 字节类型的过滤器类的抽象父类
BufferedInputStreamBufferedOutputStream 缓冲过滤器流,用于提高输入输出效率
PushBackInputStream “ ”允许将已读取的数据 压回 到流中
GZIPInputStreamGZIPOutputStreamZipInputStreamZipOutputStream
对数据进行 zip格式或 gzip格式的压缩
字符
FilterReaderFilterWriter 字符类型过滤器类的抽象父类
BufferedReaderBufferedWriter 缓冲过滤器流,用于提高输入输出效率
PushBackReader “ ”允许将已读取的数据 压回 到流中
LineNumberReader 用计数器统计从输入中读取的数据行数
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例程
import java.io.*; public class ReadLineTest { public static void main(String[] args) { try { BufferedReader br = new BufferedReader(new FileReader(args[0])); String line = null; int i = 0; while((line = br.readLine()) != null) { i++; System.out.println(i + ": " + line); } br.close(); }catch(Exception e) { e.printStackTrace(); } }}
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
对象的串行化
所谓对象串行化是指读写对象的过程,其关键之处在于以串行的流的形式来表示结构化的对象。为了实现完整对象的输入输出, java.io包中提供了两个类: ObjectOutputStream和ObjectInputStream。这两个流类与其他的字节流类的功能类似,其特殊之处在于通过它们可以读写对象。对象的串行化通常在下面两个方式下使用: 远程方法调用( RMI ——) 在远程方法调用时,需要在客户机与服务器之间传递各种对象。
——对象持久性保存 允许对象在创建它们的程序的生命周期结束后仍然存在保存,供以后的程序调用。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Serializable接口
并非所有对象都是可串行化的,如果要对某对象进行串行化,该对象的类必须实现Serializable 接口
Serializable接口是一个空接口,也就是说,它不包含任何方法的声明,该接口的作用只是表明这个类的对象可以被串行
化
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
随机文件处理
使用流的形式对文件进行读写必须顺序进行,也就是说这些文件流的数据必须按先后次序进行处理。在对某些顺序存储访问介质,例如磁带等进
行访问时,这样的文件流方式非常有用随机文件存取提供了一种更灵活的文件读写方式,它允许对文件的内容进行非顺序的访问。在
“ ”这里, 随机 是指所存取的数据不需要与以前存取过的历史数据有任何的关系。使用随即文件存取方式可以在打开一个文件后同时进行读写操作,并且可以移动文件指针使其指向文件中的任
何位置
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
随机存取文件的结构
在文件内部,文件被分成固定长度的数据块(记录)。从概念上来说,文件可以看作是一个记录数组。文件指针的移动是以记录为单位的。
文件指针
· · ·记录 记录 记录 记录 记录 记录 记录
文件
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
文件类 FileFile类的核心概念是封装用户文件系统中的某个文件或目录,它包含许多用于执行文件常规操作的方法以及检查、访问、删除、创建、更改指定的文件或目录
File类的构造函数有三个,分别根据文件名、文件路径与文件名、文件对象 (目录 )与文件名创建实例: public File(String path) public File(String path,String name) public File(File dir,String name)
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
RandomAccessFile类RandomAccessFile类的构造函数使用了两个参数,第一个参数表示要操作的文件,可以使用字符串类型的文件名也可以使用一个文件对象;第二个字符串类型的参数 mode表示了对文件的操作方式: mode ”为 r” 时表示可以从文件读取;mode ”为 rw” 时表示既可以从文件读取也可以
向文件写入RandomAccessFile类通过实现 DataInput和DataOutPut的方法来实现文件数据的读写,这些方法允许使用二进制编码形式将基本的 Java类型写入或读出文件。在 RandomAccessFile类中还提供了一些操作文件指针的方法,如通过 seek方法可以将文件指针移动到其参数所制定的位置。
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
例程
import java.io.*;public class FileTest { public static void main(String[] args) throws IOException { RandomAccessFile raf = new RandomAccessFile("foo.txt", "rw"); try { Writer out = new OutputStreamWriter(new FileOutputStream(raf.getFD()), "UTF-8"); out.write("Hello World!!"); out.flush(); raf.seek(6); out.write("Java"); out.flush(); }finally { raf.close(); } }
第十章 图形用户界面华中科技大学 IBM技术中心
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
Contents
界面布局
事件处理过程
常用的图形组件
Swing和 AWT
图形用户界面基本元素
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
图形用户界面基本元素
图形用户界面( GUI )
可以使程序提供独特的视觉效果 提高软件易用性 使用鼠标和键盘操作 $javahome$/demo/jfc/SwingSet2
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
图形用户界面基本元素
常见的图形界面元素 基本组件
• 文本框、按钮、输入框• 单选 /多选按钮、下拉框 /复选框• ……
容器• 可放置基本组件的组件• 窗体、面板、框架• 所有的组件都必须存在于容器之中• 顶层容器 Container
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
AWT和 Swing
AWT- Abstract Window Toolkit 图形界面是平台相关的 AWT是重量级的,依赖本地代码实现 不同平台外观有差异
Swing-轻量级纯 Java的图形库 基于 AWT,更丰富,功能更强大 不同平台外观一致 牺牲了性能
SWT
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
常用的图形组件
AWT java.awt.* Label、 Button、 List、 TextField… Frame、 Panel、 Container
Swing javax.swing.* JLabel、 JButton、 Jlist、 JTextField… JFrame、 JPanel
不要在容器中混合使用 AWT和 Swing组件
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
常用的图形组件
组件类名 描述
JLabel 不可编辑的文本行(可带图标)
JTextField 可编辑的文本行
JButton 按钮
JCheckBox 复选框
JRadioButton 单选框
JComboBox 下拉框
JPanel 面板
JFrame 框架
更多组件可参考 javax.swing.*
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
图形组件测试
import java.awt.*; import javax.swing.*;
public class GUITest extends JFrame { private JLabel label; private JButton button; private JCheckBox checkbox; private JRadioButton rbutton; private JTextField textfield; private JComboBox cbox; private JList list;
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
图形组件测试
public GUITest() { super("GUI Test"); Container container = getContentPane(); container.setLayout(new FlowLayout());
label = new JLabel("Im JLabel"); button = new JButton("Im JButton"); rbutton = new JRadioButton("Im JRadioButton"); textfield = new JTextField(10); textfield.setText("Im JTextField"); checkbox = new JCheckBox("Im JCheckBox"); cbox = new JComboBox(); cbox.addItem("JComboBox item 1"); cbox.addItem("JComboBox item 2"); list = new JList(); String[] data = {"JList data 1","JList data 2", "JList data 3"}; list.setListData(data);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
图形组件测试
container.add(label); container.add(button); container.add(checkbox); container.add(rbutton); container.add(textfield); container.add(cbox); container.add(list); setSize(300,200); setVisible(true); } public static void main(String[] args) { GUITest test = new GUITest(); test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
图形组件测试
运行结果
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
事件驱动
图形界面程序是通过事件来驱动的 当用户对图形组件进行操作时产生事件 如鼠标点击按钮、在输入框中输入文字等 事件对象用于记录事件详细内容 java.awt.AWTEvent
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
事件处理模型
事件处理模型中的三要素 事件源对象
• 即产生事件的图形组件如按钮、文本框等 事件对象
• 记录事件的对象,由系统产生 事件监听对象
•捕获并处理事件的对象
程序员的工作 将事件监听对象注册到事件源对象 编写处理事件的代码
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
常用的事件类
GUI事件类层次结构
java.lang.Object
java.awt.AWTEvent
ActionEvent
ItemEvent
AdjustmentEvent
ComponentEvent
java.util.EventObject
ContainerEvent
PaintEvent
FocusEvent
WindowEvent
InputEvent
KeyEvent MouseEvent
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
常用的事件监听接口
事件监听接口层次结构
java.util.EventListener
ActionListener
ComponentListener
AdjustmentListener
ContainerListener
MouseListener
TextListener
ItemListener
FocusListener
KeyListener
MouseMotionListener
WindowListener
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
事件处理示例
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class EventTest extends JFrame { private JButton button; public EventTest() { super("Event Test"); Container container = getContentPane(); button = new JButton("Click Me"); EventHandler handler = new EventHandler(); container.add(button); setSize(200,100); setVisible(true);
button.addActionListener(handler); }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
事件处理示例
class EventHandler implements ActionListener { public void actionPerformed(ActionEvent event) { ((JButton)event.getSource()).setText("Im Clicked"); } }
public static void main(String[] args) { EventTest app = new EventTest(); app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
常见的事件类和监听接口
不同的事件源根据用户的操作可能产生不同的事件对象,并由相应的事件监听对象处理
事件源 产生的事件 需要实现的监听接口JButton
ActionEvent ActionListener
JCheckBoxJRadioButton
JTextField
TextEvent TextListenerKeyEvent KeyListener
JComboBoxItemEvent ItemListener
JList
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
鼠标事件类和监听接口
所有的图形组件都能产生鼠标事件 java.awt.event.MouseEvent
处理不同的鼠标操作应实现不同的接口 鼠标点击、鼠标进入组件、鼠标离开组件
•实现 MouseListener接口 鼠标在组件中移动和拖动
•实现 MouseMotionListener
查看 Java API文档,实现这些接口应该定义哪些方法?
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
事件适配器
由 JavaAPI提供的实现了相应事件监听接口的抽象类,可直接使用而无需定义额外的事件处理类,从而简化事件处理代码 addMouseListener(new MouseAdapter() { mouseClicked(MouseEvent event){ // … } });
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
界面布局
设计图形界面时,程序员应该考虑组件在容器中的位置、大小和组件之间的排列方式
如果没有使用布局管理器,程序员需要确定每个组件的大小和在容器中的坐标: JButton btn = new JButton(“Ok”);
btn.setBounds(10, 20, 60, 20); add(btn);
当窗口大小改变时,组件不会自动调整位置和大小
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
布局管理器
Java使用布局管理器简化组件布局工作 决定图形组件的排列形式 实现接口 java.awt.LayoutManager
使用布局管理器的好处 当程序窗口尺寸改变时,布局管理器能自动调整组件的位置和大小
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
常用的界面布局形式
常用的布局管理器 FlowLayout BorderLayout BoxLayout CardLayout GridLayout GridBagLayout
通过容器组件的 setLayout()方法设置容器中的组件排列形式,如: setLayout(new FlowLayout());
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
FlowLayout
最简单的界面布局方式,从左至右、从上至下按顺序依次摆放组件: setLayout(new FlowLayout()); add(button1); add(button2); add(button3); add(button4); add(button5);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
BorderLayout
按东南西北中五个区域摆放组件,通常作为窗口主框架 setLayout(new BorderLayout()); add(“North”, button1); add(“West”, button2); add(“East”, button3); add(“South”, button4); add(“Center”, button5);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
GridLayout
各组件占用相等的格空间 setLayout(new GridLayout(3, 2)); add(button1); add(button2); add(button3); add(button4); add(button5);
华中科技大学 IBM技术中心
HUST & IBM Computer Tech. Center
GridBagLayout
最复杂、最灵活的布局方式,将容器空间划分成网格,每个组件可占用多个网格。通常还需要使用 GridBagConstraints对象设置组件占用的格数和方位。加入组件前,需要调用布局管理器对象的 setConstraints()方法设置组件的显示约束。
欢迎提问
top related