第1章 Java快速入门
1.1 Java简介
1.1.1 Java的起源与发展
Java是美国Sun Microsystems公司于1995年5月正式发布的程序设计语言,它是前身是公司为智能消费类家用电器(如:电视机、电话、闹钟、烤面包机)研究而开发的,直到1993年Web开始在Internet上盛行,开发小组试着将这一技术转移到Web网络上,并获得了空前的成功。
为了促销和法律的原因,1995年Oak更名为Java,小插曲:一天Java小组成员正在喝Java咖啡时,议论给新语言取名字问题,有人提议用Java(Java是印度尼西亚盛产咖啡的一个岛屿),这个提议得到了其他成员的赞同,于是就采用了Java来命名此新语言。
表:Java的发展历史
时间 | 描述 |
1991 | Sun公司进军消费电子产品(IA)市场 |
1991.4 | Sun成立“Green”小组,以C++为基础开发新的程序设计语言,并将其命名为Oak |
1992.10 | Green小组升格为First Person公司,他们将Oak的技术转移至Web上,并把Oak改名为Java |
1993~1994 | Web在Internet上开始流行,致使Java得以迅速发展并成功 |
1995.5 | Sun公司正式发表Java与HotJava产品 |
1995.10 | Netscape与Sun合作,在Netscape Nevigator中支持Java |
1995.12 | 微软公司IE加入支持Java和行列 |
1996.2 | Java Beta测试版结束,Java 1.0版正式诞生 |
1997.2 | Java发展至1.1版,Java的第一个开发包JDK(Java Development Kit)发布 |
1999.7 | Java发展至1.2版 |
2000.9 | Java发展至1.3版 |
2001.7 | Java发展至1.4版 |
Java最新版本为1.4版,Java的早期版本称为JDK,1.2版之后改名为Java 2。到今天,Java的大家庭中已有了三个主要成员:
(1)J2ME:Java 2 Micro Edition用于嵌入式的Java消费电子平台。不论是无线通讯、手机、PDA等小型电子装置都可采用其作为开发工具及应用平台。
(2)J2SE:Java 2(Software Development Kit)Standard Edition是Java最通行的版本,是用于工作站、PC机的Java标准平台。也是本书应用程序的使用版本。使用Java SDK软件包。
(3)J2EE:Java 2 Enterprise Edition可扩展的企业应用Java 2平台,它提供了企业e-Business架构及Web Services服务,其深受企业用户欢迎之处是开放的标准和优越的跨平台能力。
1.1.2 Java语言特点
见书P1~4
1.1.3 Java的用途
1.用于Web的Applet
Applet是嵌入到HTML中的小应用程序,但Java语言的全部功能都可以实现,能解决一些传统编程语言很难解决的问题,如多线程、网络连接、分布式计算等。
2.独立运行的Application
Java也是一种高级编程语言,和其他语言有许多共同之处。
3.数字设备领域
目前,Sun正把Java的目标从传统的计算机应用向其他数字设备领域扩展。
4.Java应用的发展趋势
可以预见,Java在智能Web服务、移动电子商务、分布计算技术、企业的综合信息化处理、嵌入式Java技术等方面必将得至越来越广泛的应用。
1.2 Java的运行环境
1.2.1 SDK的下载与安装
2.下载SDK
www.java.sum.comà单击右边“J2SE 1.4.2 SDK”à一种在线安装“Windows Installation”或离线安装“Windows Offline Installation”,单击SDK列对应的“DOWNLOAD”à“ACCEPT”同意Sun公司协议à“Download j2sdk-1_4_2_07-windows-i586.exe”
注:不同时期,网页内容有所改变
1.2.2 配置Java运行环境
1.设置Windows 95/98/Me
在C:\autoexec.bat文件中,添加以下两行内容:
set path=%path%;E:\j2sdk1.4.2_01\bin
set classpath=.;E:\j2sdk1.4.2_01\lib\;%classpath%
说明:(1)set path是让Java程序设计者在任何目录下都可以运行bin目录下的工具文件,如:javac.exe , java.exe , javap.exe和javadoc.ex ;
(2)set classpath是让Java虚拟机找到所需要的类库;
(3)“E:\j2sdk1.4.2_01”与本人安装Java的具体目录而改变;
2.设置Windows XP/NT/2000
右击“我的电脑”à“属性”à“高级”à“环境变量”在“系统变量”或“用户变量”中编辑path,在变量值中加入“;E:\j2sdk1.4.2_01\bin”
新建变量名“classpath”,变量值是“.;E:\j2sdk1.4.2_01\lin”
3.设置DOS起始位置
(1)在Windows XP/NT/2000系统中
“开始”à“程序”à“附件”à右击“命令提示符”à“属性”à“快捷方式”à在“起始位置”中输入自己想要直接进入的目录
说明:若直接在“运行”对话框中输入cmd则不行
(2)在Windows 95/98/Me系统中
可以用cd做批处理文件
-
- 初步了解Java程序
1.3.1 编写第一个Java Application程序
使用任何一个文件编辑器输入:
public class Hello{
public static void main(String args[]){
System.out.println("欢迎你学习Java语言!"); } }
说明:(参见P19)
(1)public class指明是一个公共类,最多只能有一个公共类;
(2)main( )方法有且只有一个,且严格按照格式定义;
(3)String args[]是传递给main( )方法的参数,名为args,它是类string的一个实例,参数可以没有,可以一个或多个,每个参数用“类名 参数”来指定,多个参数间用逗号分隔;
(4)Java区分大小写;
(5)一定以公共类名相同的主文件名Hello.java存盘,且大小写一致;
1.3.2 Java程序的编译
在DOS窗口中输入:Javac Hello.java
功能:将文本文件Hello.java编译成可执行的Hello.class字节码文件
1.3.3 运行Java程序
在DOS窗口中输入:Java Hello[.class]
1.3.4 Java的Applet小程序(补充)
1.类定义
使用任何一个文件编辑器输入:
import java.awt.Graphics;
import java.applet.Applet;
public class Hello2 extends Applet{
public String s;
public void init(){
s=new String("欢迎你学习Java语言!");
}
public void paint(Graphics g){
g.drawString(s,50,50);
}
}
2.编译成字节码文件
在DOS窗口中输入:Javac Hello2.java 得Hello2.class文件
3.编写Html文件
使用任何一个文件编辑器输入:
<HTML>
<applet code="Hello2.class" width=500 height=300>
<!—注意“Hello2.class”的大小写,其余不区分大小写>
</applet>
<HTML>
以SC.html存盘
说明:因Hello2.java文件没有Main方法,所以不能独立运行
4.运行
方法一:双击SC.html文件即可调用IE打开
方法二:用Appletviewer工具,在Dos中输入:appletviewer SC.html
第2章 Java基本语法
2.1 Java语言的基本元素
2.1.1 标识符
标识符规则:必须以字母、下划线、“$”或汉字开头,后面的字符可以是字母、数字、下划线、“$”和汉字的一串字符
说明:(1)不能是Java保留的关键字;
(2)常量名一般以大写字母,变量名用小写字母,类名以大写字母开始;
(3)区分大小写,如ad、Ad、aD、Da是四个不同的标识名。
2.1.2 关键字
P20 表2.2
2.1.3 分隔符
1.注释符
(1)// 注释一行
以“//”开始,终止于行尾,一般作单行注释,可放在语句的后面
(2)/*……*/ 一行或多行注释
以“/*”开始,最后以“*/”结束,中间可写多行。
(3)/**……*/
以“/**”开始,最后以“*/”结束,中间可写多行。这种注释主要是为支持JDK工具javadoc而采用的。
2.空白符
如空格、回车、换行和制表符(Tab键)。系统编译程序时,只用空白符区分各种基本成分,然后忽略它。
3.普通分隔符
(1)“.”点号:用于分隔包、类或分隔引用变量中的变量和方法
(2)“;”分号:Java语句结束的标志;
(3)“:”冒号:说明语标号;
(4)“{ }”大括号:用来定义复合语句、方法体、类体及数组的初始化;
(5)“[ ]”方括号:用来定义数组类型及引用数字的元素值;
(6)“( )”圆括号:用于在方法定义和访问中将参数表括起来,或定义运算的先后次序。
2.2 数据类型
Java要求在程序中使用任何变量之前必须先声明其类型。
Java的数据类型分为:
- 基本类型:整型、浮点型、布尔型、字符型
- 数组类型:一维数组和多维数组
- 复合类型:类、接口
2.2.1 基本数据类型
表2.3 Java基本数据类型
说明 | 类型 | 位长/b | 默认值 | 取值范围 |
布尔型 | boolean | 1 | false | true , false |
字节型 | byte | 8 | 0 | -128~127 |
字符型 | char | 16 | ‘\u0000’ | ‘\u0000’~’\uffff’即0~65535 |
短整型 | short | 16 | 0 | -32768~32767 |
整型 | int | 32 | 0 | -231~231-1 |
长整型 | long | 64 | 0 | -263~263-1 |
浮点型 (单精度) | float | 32 | 0.0 | +-1.4E-45或+-3.4028235E+38 |
双精度 | double | 64 | 0.0 | +-4.9E-324 或 +-1.797693134862315E+308 |
说明:
(1)一般情况下,没小数点的数字是int型,有小数点的数是double型;
(2)String(字符串)型,如:“合肥”、“I am student” ;
(3)Java的char类型采用UniCode(国际编码标准)的新字符处理方式,即大字符编码方案,汉字和字母均看作是一个字符,占两个字节;
(4)Java程序是定义的变量若没有赋初值,Java取默认值。
C++基本数据类型有:整型(int)、字符型(char)、浮点型(float,double)、常量型
类型名 | 长度(字节) | 取值范围 |
Char(signed char) | 1 | -128~127 |
Unsigned char | 1 | 0~255 |
Short(short int) | 2 | -32768~32767 |
Unsigned short | 2 | 0~65535 |
int(signed int) | 2 | -32768~32767 |
Unsigned int | 2 | 0~65535 |
Long(signed long) | 4 | -2147483648~2147483647 |
Unsigned long | 4 | 0~4294967295 |
Float | 4 | +-3.4*10e-38 ~ +-3.4*10e38 |
Double | 8 | +-1.7*10e-308~ +-1.7*10e308 |
Long double | 8 | +-1.7*10e-308~ +-1.7*10e308 |
2.2.2 直接量与常量
直接量(literal)是指在程序中直接给出的一个符号串,即其它语言称为的常量。
Java的常量用final说明,约定常量标识符一般全部使用大写字母,常量在程序执行时不可更改。
如:final int i=1;
i=i+1; //错,i是final(常量),不可更改值
1.布尔型常量
true 、 false
注意:Java中的布尔型常量不能与0、-1、1等数字
例:
boolean A,b,C;
A=false;
b=true;
C=1; //错
boolean D=True; //错,“True” 首字大写
2.整型常量
例: 45 , 045 ,0x45 , 45L
int a=10 ; // 十进制
int b=020 ; // 八进制 以“0”(零)开头
int c=0x3A ; // 十六进制 以“0x”开头
int d=71 , Y=91 ; // 对
int M=0xd1 , N=091 ; // 错 “091”是八进制,不能有9
说明:整型常量默认为32位int型,若在数值后加L或l,则表示为64位长整型
3.浮点型常量
例: 3.45 , 4.512E12 4.5F 4.5D
说明:(1)默认类型为64位double双精度类型(D或d),数字后面加F或f则是32位float单精度(实数)类型
(2)double类型值有效空间大,但运行慢,结果精度不高
float a , b ; double x , y , z ;
a=7.4 ; //错, 7.4默认是double型,不能赋予精度低的float型
b=7.4F ;
x=7.4E5;
y=7.4E5D ;
z=7.4E5F; //对
4.字符常量
字符常量是由单引号括起来的单个字符,它可以是UniCode字符集中的任意一个字符。如 ‘A’ ‘#’ ‘宋’ ‘6’
转义符号见P23 表2.4
5.字符串常量
用一对双引号起来的字符序列。
例: “ABCD” “学习Java”
public class SC{
public static void main(String arg[]){
String a="我是安徽\n合肥人"; // “\n” 表示换行
String b='%' ; //错 ‘%’是字符型,不能赋予String型
System.out.println(A); //错 A改为a
} }
-
-
- 变量
-
Java通常用小写字母或单词作为变量名。
变量具有名字、类型、值三元素
1.变量的声明
格式:类型 变量名[,变量名]=初值,… ;
赋值:[类型] 变量名=值
如:int a=5 , b=6 , c , d ;
String s=”合肥” ;
float m , n ;
m=6.78f ;
说明:
(1)变量名必须在作用域中是唯一的,不同作用域中才允许相同名字的变量出现;
(2)只要在同一代码块没有同名的变量名,可以在程序中任何地方定义变量,一个代码块就是两个相对的“{ }”之间部分。
2.变量的使用范围
每个变量的使用范围只在定义它的代码块中,包括这个代码块中包含的代码块。
在类开始处声明的变量是成员变量,作用范围在整个类;
在方法和块中声明的变量是局部变量,作用范围到它的“}”;
见P25 例2.4:
例:public class SC{
int i=0;
public static void main(String arg[]){
int i=1;
System.out.println(i); } } // 输入 1
3.变量类型的转换
Java可以将低精度的数字赋值给高精度的数字型变量,反之则需要强制类型转换。
强制转换格式:(数据类型)数据表达式
如:int i;
float f=(float)34.6; // 34.6默认是双精度,float f=34.6F也对
i=(int)f;
System.out.println(f); // 输出34.6
System.out.println(i); // 输出34
byte short char int long float double
字节型 短整型 字符型 整型 长整型 单精度实型 双精度实型
低 高
2.3 运算符与表达式(与C、C++相同)
2.3.1 赋值运算符
简略形式 | 非简略形式 |
i+=j | i=i+j |
i-=j | i=i-j |
i*=j | i=i*j |
i/=j | i=i/j |
I%=j | i=i%j |
例:a=b=c=0 ; 相当于c=0 , b=c , a=b ;
例: int k=10; double x=10, y=20 ;
k/=4 ; // 2
x+=10; // 20
y*=y; // 400
例: int i=10 , j=3 ;
i*=j+2 // 50
2.3.2 算术运算符
见P28 表2.7
例 int i=1;
System.out.println(i++); // 输出 1
System.out.println(++i); // 输出 3
2.3.3 关系运算符
等于 | 不等于 | 小于 | 小于等于 | 大于等于 | 大于 |
== | != | < | <= | >= | > |
如:public class SC{
public static void main(String arg[])
{ boolean x , y ;
int i=5 , j=2 ;
x=(i-4)= =(j-1) ;
int a=1 ; double b=1.0 ;
y=a= =b;
int m=65 ; char n='A' ;
System.out.println(x) ; // 输出true
System.out.println(y) ; // 输出true
System.out.println(m= =n) ; // 输出true
}}
2.3.4 条件运算符
格式:条件表达式 ? 表达式2 :表达式3
功能:条件表达式为true,取“表达式2”值,为false,取“表达式3”的值
例: int a=0x10 , b=010 , max ;
max=a>b ? a : b ;
System.out.println(max) ; // 输出16
2.3.5 逻辑运算符
见P29 表2.9
2.3.6 位运算符(不做要求)
2.3.7 其他运算符
见P32 表2.11
instanceof : 对象运算符,用于测试一个对象是否是一个指定类的实例
例:有一个称为shape的类,shape的子类是polygonShape,如果有一个存储shape的变量实例shapeHolder,如何知道它是否是一个polygonShape呢?下述代码段会帮助解决这个问题:
shape shapeHolder ;
if (shapeHolder instanceof polygonShape)
{ polygonShape polygon=( polygonShape) shapeHolder ;
…………
………… }
当处理保存某一公用父类的子类对象的数据结构时,会经常遇到上面提及的情况。假设我们有一个基于画图程序的对象,并且存储了用户绘制的所有形状,若要打印这些数据,就要有一个循环遍历这些数据结构并打印每一形状,如果一种特殊的形状需要特殊的指令进行打印,就需要使用instanceof运算符。
new : 对象实例化运算符,实例化一个对象,即为对象分配内存
+ : 字符串合并运算符,
表:字符串创建规则
操作数 | 规 则 |
Null变量 | 取值为空(null)会产生null字符串 |
整数 | 整数会被转换成十进制,表示字符串,如是是负数,前面会加上“-”号。 |
浮点数 | 被转换为紧缩格式的字符串,如果长度超过10个字符,会以指数形式表示。 |
字符 | 被转换为长度为1的包含相同字符的字符串 |
布尔值 | 转换成“true”或“false” |
对象 | 对象的方法toString( )会被调用 |
例:String a="Hi" , b="你好" ;
int i=42 ;
float j=42.0f ;
boolean f=i==j ;
double d=489.47 ;
System.out.println(a+b) ; // 输出Hi你好
a=a+f ;
System.out.println(a); // 输出Hitrue
System.out.println(b+d); // 输出你好489.47
2.3.8 运算优先级
见P32 表2.12
例: int a=3 , b=6 , k ;
k=a+=b-=2 ; // 先计算b-=2, 得4,再计算a+=4
System.out.println(k) ; // 输出 7
2.4 数组
数组是有序数据的集合,数组中的每个元素具有相同的数组名,根据数组名和下标来唯一确定数组中的元素。使用时要先声明后创建
2.4.1 一维数组的声明
格式: 数据类型 数组名[ ] 或 数据类型 [ ]数组名
例: int a[] ; String s[] ; char []c ;
说明:定义数组,并不为数据元素分配内存,因此“[ ]”中不用指出数组中元素个数。
2.4.2 一维数组的创建与赋值
创建数组并不是定义数组,而是在数组定义后,为数组分配存储空间,同时对数组元素进行初始化
1.用运算符new分配内存再赋值
格式:数组名=new 数据类型[size]
例:int a[] ; String s[] ; char []c ;
a=new int[3] ; // 产生a[0] , a[1] , a[2] 三个元素
s=new String[2] ; c=new char[5] ;
a[0]=8 ; a[1]=8 ; a[2]=8 ;
s[1]=”网络” ;
int intArr[]=new int[3] ; // 声明和分配内存并在一起
char chArr[]=new char[6] ; // 声明和分配内存并在一起
System.out.println(a[0]+a[1]) ;
2.直接赋初值并定义数组的大小
例:int i[]={4,5,010,7,3,2,9} ;
String names[]={“张三”,”李四”,”王五”,”宋七”} ;
char c[]={‘a’,’b’,’c’,’北’,’京’} ;
3.测试数组长度(补充)
格式:数组名.length
char c[]={‘a’,’b’,’c’,’北’,’京’} ;
System.out.print(c.length) ; // 输出5
2.4.3 多维数组
以二维数组为例
例:int d[][] ; // 定义一个二维数组
d=new int[3][4] ; // 分配3行4列数组内存
char c[][]=new char[2][3] ; // 定义和分配在一起
int a[][]=new int[2][] ;
a[0]=new int[3] ; // 第二维第一个元素指向3个整型数
a[1]=new int[5] ; // 第二维第一个元素指向5个整型数
// Java可以第二维不等长
int i[][]={{0},{1,4,5},{75,6},{8,50,4,7}} ; //定义和赋初值在一起
System.out.println(i[2][1]) ; // 输出6
System.out.println(i[1][2]) ; // 输出5
System.out.print(i.length) ; // 输出4
System.out.print(i[1].length); // 输出3
例: 下面数组定义哪些是正确的
int a[][]=new int[10,10] //错
int a[10][10]=new int[][] //错
int a[][]=new int[10][10] //错
int []a[]=new int[10][10] //对
int [][]a=new int[10][10] //对
第3章 Java语句及其控制结构
3.1 Java程序结构
3.1.1 Java程序构成
见P38 例3.1
说明:
(1)Java源程序一般包括Java包引入(如果有的话)和类定义两部分;
(2)Java程序必须包含一个可被外界所直接调用的类,即主类;
(3)一个Java程序可以定义多个类,但只能有一个主类,Java Applet程序的主类是继承自Applet的子类;Java Application程序的主类是包含main方法的类,应用程序从main方法开始执行;
(4)类定义由类声明语句和类体组成;
(5)类声明语句用来说明类的名称、访问权限及类的属性;
(6)类体也由两部分组成:成员变量和成员方法;
(7)成员变量为类中定义的变量(又称属性、域),用来说明类的状态和特性。定义成员变量需要声明成员变量的名称、类型。
(8)成员方法为类中定义的方法,用来实现类的功能和行为,是完成任务的关键。Java Application程序中一定要有main()主方法。而Java Applet程序一般要有init( )初始化方法或paint(Graphics g)画图方法;
(9)类体中除了成员变量和成员方法说明语句外没有其他语句,Java规定所有操作性语句必须放在成员方法中;
(10)Java方法类似于其他语言中的函数,可以调用,可以有返回值。成员方法可以继承父类的方法,也可以自定义成员方法。方法中也可以定义局部变量。
3.1.2 Java语句
语句以分号“;”作为结束标志
Java语句分为说明性语句和操作性语句。
说明性语句用来说明包和类的引入、类的声明、变量的声明
如:import java.applet.Applet ;
操作性语句有表达式语句、复合语句、选择语句和循环语句等
1.表达式语句
int k, i=3 , j=4;
k=i*j;
2.复合语句
复合语句也称为块(block)语句,是包含在一对大括号“{ }”中的任意语句序列。从语法上讲,一个复合语句被视为一个简单语句。
3.2 选择语句
3.2.1 if语句
格式: if (条件表达式)
语句
功能:条件表达式为true就执行语句
例: int i=70; char c='A';
if(i>=c) System.out.println("A小");
System.out.println("结束");
3.2.2 if……else语句
格式: if (条件表达式)
语句1
else
语句2
功能:条件表达式为true就执行语句1,为false执行语句2
例:if('A'>'a')
System.out.println("A比a大") ;
else
System.out.println("A比a小") ; // A65,a97,所以输出A比a小
System.out.println("结束");
3.2.2 if……else 复合结构
格式: if(条件表达式1) 语句1
else if (条件表达式2) 语句2
…………
else if (条件表达式n) 语句n
else 语句 n+1
功能:如果某个条件表达式的值为true,就执行它后面的语句,其余部分被忽略,若条件表达式都为假,执行else后语句。
例:public class SC{
public static void 输入分数(int a){
char 级别;
if (a>=90) 级别='优';
else if (a>=80) 级别='良';
else if (a>=60) 级别='中';
else 级别='差';
System.out.println("考试等级为 "+级别); }
public static void main(String arg[]) throws Exception{
if(arg.length==0) System.out.println("您没有输入任何参数") ;
else if(arg.length==1)
输入分数(Integer.parseInt(arg[0])); //arg[0]强制转换成int型
else {System.out.println("您输入的参数太多了") ;
System.out.println("命令行参数个数为"+arg.length) ; }
} }
执行:java SC 75 // 输出:考试等级为 中
java SC // 输出:您没有输入任何参数
java SC 75 86 // 输出:您输入的参数太多了
// 命令行参数个数为2
3.2.4 switch开关语句
格式:switch (表达式) {
case 常量1:[语句块1;] [break;]
…………
case 常量n : [语句块n;] [break;]
[default: 语句块n+1;]
}
功能:先计算switch表达式,再与每个case常量表达式值相比较,若相同,则执行相应语句被执行。若都不同,则执行default语句n+1(若有的话)
说明:
1.switch后表达式必须是整型,字符型;
2.每个case的常量必须不同;
3.若没有break,程序将继续执行下一个case语句;
4.default位置可任意,但要注意break
例:int a=80,b=9;
char oper='/';
switch(oper) {
case '+' : System.out.println(a+"+"+b+"="+(a+b)); break;
case '-' : System.out.println(a+"-"+b+"="+(a-b)); break;
case '*' : System.out.println(a+"*"+b+"="+(a*b)); break;
case '/' : System.out.println(a+"/"+b+"="+(a/b)); break;
default : System.out.println("操作符错误");
结果:80/9=8 //因为是整型数相除
思考:
(1)没有break的情况(将会执行“/”,“*”,“default”行);
(2)若操作数都不符,default改变位置,能否执行?(能),但后面要加“break”
例: public class SC{
public static void main(String a[])
{ int i=0,j=5;
switch(i) {
case 0: switch(j){
case 1: System.out.print("A"); break;
case 2: System.out.print("B"); break;
default:System.out.print("C") ; break; }
case 1: switch(j){
case 4: System.out.print("X"); break;
case 5: System.out.print("Y"); break; }
default: System.out.print("Z"); break; }}}
运行结果: CYZ
3.3 循环语句
3.3.1 for循环语句(与C、C++相同)
格式: for(赋初值;判断条件;循环控制变量增减方式)
{ 语句块 }
功能:(1)第一次进入for循环时,对循环控制变量赋初值;
(2)根据判断条件检查是否要继续执行循环。为真执行循环体内语句块,为假则结束循环;
(3)执行完循环体内语句后,系统根据“循环控制变量增减方式”改变控制变量值,再回到步骤(2)根据判断条件检查是否要继续执行循环。
例:public class SC {
public static void main(String args[]) {
int j=0 ;
for(int i=0 ; i<=5 ; i++) {
j+=i ;
System.out.println("j="+j) ; }
} }
运行结果:j=0
j=1
j=3
j=6
j=10
j=15
3.3.2 while循环语句
格式:while (条件表达式)
循环语句块
功能:先计算条件表达式,为true,则执行循环语句块,为false则跳出循环。
例:public class SC{
public static void main(String args[]) {
char c='a' ;
while(c<='e') {
System.out.print(c+" ") ;
c=(char)(c+1) ; }
} }
运行结果:a b c d e
3.3.3 do…while循环语句
格式: do { 循环体 }
while(条件表达式) ;
注意:while后面的“;”
3.3.4 循环语句的嵌套
例:public class SC {
public static void main(String args[])
{ int i , j ;
for (i=1;i<=9;i++)
{ for (j=1;j<=9;j++)
System.out.print(i+"*"+j+"="+(i*j)+"\t");
System.out.println();}
} }
运行结果:1*1=1 1*2=2…………1*9=9
2*1=2 2*2=4…………2*9=18
……………………
9*1=9 9*2=18…………9*9=81
-
-
- 循环语句小结
-
(1)初始化部分:用来设置循环的一些初始条件,计数器清零等;
(2)循环体部分:这是反复被执行的一段代码,可以是单语句,也可以是复合语句;
(3)迭代部分:这是当前循环结束,下一次循环开始时执行的语句,常用来使计数器加1或减1;
(4)终止部分:是一具布尔表达式,每一次循环要对该表达式求值,以验证是否满足循环终止条件。
3.4 跳转语句
Java支持3种跳转语句:break , continue , return
3.4.1 break语句
格式:break ;
功能:(1)退出switch结构;
(2)退出当前一层循环。
例:见P51
3.4.2 带标号的break语句
格式:标识符: //标识符应在break前面
……
break 标识符 ;
功能:直接跳转到标识符处,可以退出多重循环;
例:public class SC{
public static void main(String args[]) {
int i,j,k=0;
ABC: for(i=0,j=0;i<10 && j<20;i++,j+=5) {
for(;k<10;) {
k = k + 1;
break ABC; }
System.out.println("i = " + i + " j = " + j); }
System.out.println("Exit for loop==> i = " + i);
System.out.println("Exit for loop==> j = " + j);
System.out.println("Exit for loop==> k = " + k);
} }
运行结果:Exit for loop==> i =0
Exit for loop==> j =0
Exit for loop==> k =1
若去除“break ABC;”语句运行结果:
i=0 j=0
i=1 j=5
i=2 j=10
i=3 j=15
Exit for loop==> i =4
Exit for loop==> j =20
Exit for loop==> k =10
例: int i=3 j;
outer: while(i>0) {
j=3;
iner: while(j>0) {
if(j<2) break outer;
System.out.println(j+”and”+i);
j--;
} i-- ; }
3.4.3 continue语句
格式:continue ;
功能:只有用在循环结构中,跳过循环体中尚未执行的语句,重新开始下一轮循环。从循环体第一个语句开始执行。
例:public class SC {
public static void main(String args[]) {
int m=0 ;
do { m++ ;
if(m/3==0) continue ; //去除此行语句则输出5个“您好!”
System.out.println("您好!") ; }
while(m<5) ; } }
运行结果:输出3个“您好!”
3.4.4 带标号的continue语句
格式:标识符:
……
continue 标识符;
功能:用标号标出想跳到的语句,继续重复执行程序。
说明:“break 标识符;”是结束循环;“continue 标识符;”是继续循环。
例:P53
3.4.5 return语句
格式:return [表达式] ;
功能:返回调用的语句,执行它的下一条语句,可以带参数返回。
说明:当方法用void声明时,说明不需要返回值(即返回类型为空),使用不带参数return语句。不带参数return语句可以省略。
例:public class SC {
public static int Mul( )
{ int m=1;
for (int i=1 ; i<=5; i++)
m=m*i;
return m; }
public static void main(String args[])
{ System.out.println("5!="+ Mul( )); } }
运行结果:5!=120
作业:P56 3-3
方法一:public class SC{
public static void main(String arg[]){
char c='A';
while(c<='E') {
switch(c)
{case 'A': System.out.println("A 等级的分数段是90分以上");break;
case 'B': System.out.println("B 等级的分数段是80~90分以上");break;
case 'C': System.out.println("C 等级的分数段是70~80分以上");break;
case 'D': System.out.println("D 等级的分数段是60~70分以上");break;
case 'E': System.out.println("E 等级的分数段是60分以下");break; }
c++;}}}
方法二:import java.io.* ;
public class SC{
public static void main(String arg[]) throws IOException{
char c=(char)System.in.read();
// System.in.read( )只接受一个键盘输入字符,且是int型
switch(c)
{case 'A': System.out.println("A 等级的分数段是90分以上");break;
case 'B': System.out.println("B 等级的分数段是80~90分以上");break;
case 'C': System.out.println("C 等级的分数段是70~80分以上");break;
case 'D': System.out.println("D 等级的分数段是60~70分以上");break;
case 'E': System.out.println("E 等级的分数段是60分以下");break;
default : System.out.println("输入等级错误!"); }}}
第4章 面向对象编程
4.1 面向对象基本概念
4.1.1 对象
对象:相关数据和方法的集合
4.1.2 封装
封装的含义是把类设计成一个黑箱,使用者只能看见类中定义的公共方法,而看不到方法实现的细节,也不能直接对类的数据进行操作,迫使用户通过接口去访问数据。
封装是一种信息隐蔽技术,封装的定义为:
(1)一个清楚的边界;所有对象的内部软件的范围被限定在这个边界内;
(2)一个接口:这个接口描述该对象和其他对象之间的相互作用;
(3)受保护的内部实现:这个实现给出了由软件对象提供的功能的细节,实现细节不能在定义这个对象的类的外面访问。
4.1.3 消息
对象的行为由方法来实现,消息传递是对象之间进行交互的主要方式。
构成消息的3个要素是:接收消息的对象、接收消息后进行处理的方法和方法所需要的参数。
4.1.4 类
类是一种复杂的数据类型,是将不同类型的数据和这些数据相关的运算(即方法)封装在一起的集合体。它是对所要处理的问题的抽象描述。
4.1.5 继承
一个类的上一层称为父类,而下一层称为子类,一个类可以继承其父类的变量和方法,且这种继承具有传递性。
4.1.6 接口
接口可以看成是为两个不相关的提供交流途径的工具,是一个包含方法定义和常量值的集合。
Java不支持多继承,子类只能有一个父类,有时需要使用其他类中的方法,但又无法直接继承,这时可以使用接口技术。
接口不需要建立继承关系,就可以使两个不相关的类进行交互。
体现面向对象思想的程序:见P60
4.2 Java的类与对象
Java程序的所有数据类型都是用类来实现的,Java语言是建立在类这个逻辑结构之上的,所以Java是一种完全面对象的程序设计语言。类是Java的核心,Java程序都由类组成,一个程序至少包含一个类,也可以包含多个类。对象是类的实例,Java程序中可以使用标识符表示对象,并通过对象引用类中的变量和方法。
Java程序员的任务就是设计出类和对象来解决实际问题。创建类时既可以从父类继承,也可以自行定义。
4.2.1 类的创建
格式: [修饰符] <class> <类名> [extends 父类] [implements接口]
{ 类体(成员变量和成员方法) }
修饰符:指明类在使用时所受到的限制,包括类访问权限[public]和其他特性[abstract],[final]
例:public class C1 { …… }
public class C2 extends Applet implements ActionListener
{……}
1.class <类名>
告诉编译器这是一个类
2.Public(公共的)
在没有任何修饰符的默认情况下,类只能被同一个源程序文件或同一个包中的其他类使用,加上public后,该类可以被任何包中的类使用,称为公共类。
注意:在同一个源程序文件中不能出现两个及以上的public类,否则编译器会告诉你将第二个public类放在另一个文件中。
3.abstract(抽象的)
abstract说明的类称为抽象类,不能用它实例化一个对象,它只能被继承,abstract方法是不含代码的方法,需要以后的子类中重载实现,abstract类的子类必须实例化(实现)abstract方法,或将自己也声明为abstract。这对于定义概念是有用的。
4.final(最终的)
final说明的类称为最终类,最终类不能被继承
Java中的String和Array类就是一个final类
注意:final和abstract不能同时修饰一个类(出错),这样的类没有意义
无修饰符是默认方式,即不使用上述三种修饰符。因此它们的优势和限制都没有作用,无修饰符的类可以被其他类访问和继承,但只有在相同程序包中的那些对象才可能使用这样的类。
5.extends(继承)父类名
extends告诉编译器创建的类是从父类继承下来的子类,父类必须是Java系统类或已经定义的类。
从父类继承,可以提高代码重用性,不必从头开始设计程序。
6.implements(实现)接口名
implements告诉编译器类实现的接口,接口必须有定义,一般为系统类。
接口是消息传递的通道,通过接口,消息才能传递到处理方法中进行处理。implements说明你的类可以实现的一个或多个接口,如果有多个接口,要用逗号分隔。
例:import java.awt.*;
import java.applet.*;
public class ch3 extends Applet{
public void paint(Graphics g) {
g.drawString("Hello Java!I love you^_^",25,25); } }
<html>
<head>
<title>Hello Java Applet测试</title>
</head>
<APPLET code=ch3.class width=200 height=40>
抱歉,你的浏览器不支持JAVA APPLET┅
</APPLET>
</html>
4.2.2 对象的创建
类的对象的模板,Java运行应该是用类创建实例化对象。
一旦任务完成,对象就会被垃圾收集器收回,完成它从创建、使用到清除。
见P66 例4.3
1.创建对象与构造方法
创建对象格式: 类名 对象名=new 类名([参数]) ;
说明:(1)运算符new为对象分配内存空间;
(2)生成对象的最后一步是执行构造方法;
(3)创建对象相当于定义一个变量,即分两步进行。
创建对象分成两步: 类名 对象名 ;
对象名=new 类名([参数]) ;
2.对象初始化的说明
(1)系统如何对变量初始化
当用new创建了一个对象时,系统会为对象中的变量进行初始化。即不但为变量分配相应的存储单元,还设置相应初值。系统为byte , short , int , long类型设置初值为0;float类型变量初值为0.0f;double类型变量初值为0.0;char字符型变量为’u\0000’;boolean逻辑变量初值为false;引用类型初值勤为null。
(2)构造方法的作用与构成
new操作符为对象分配内存后将调用类的构造方法确定对象的初始状态,初始化所有变量。
构造方法功能:创建对象时,用给定的值,将对象初始化
构造方法特点:
(1)构造方法名与类名相同,且不指定类型说明;
(2)可以重载,即可以定义多个参数个数不同的函数,系统可以根据参数的不同,自动调用正确的构造方法;
(3)程序中不能直接调用构造函数,在创建对象时系统自动;
(4)可以不设计构造方法,若在初始化时还要执行一些其他命令,就必须设计构造方法,因为Java规定命令语句不能出现在类体中,只能放在方法中。
重载:参数不同可以是数量不同,类型不同,或两者都不同,但重载方法必须有相同的方法名和相同的返回类型。
例:class ABC{
public ABC( ) {……} // 无参数构造方法
public ABC(int a, int b ) {……} // 带两个参数构造方法
public ABC(String a ) {……} // 带一个个参数构造方法
public int ABC(int a) {……} // 错,构造方法不能有类型返回值
public void ABC( ) {……} // 错,构造方法不能有类型返回值
}
例:public class SC{
public static void main(String args[]){
sc1 a=new sc1( ) ;
sc1 b=new sc1("练习") ;
System.out.println("程序结束!");} }
class sc1{
public sc1( ) {System.out.print("开始");}
public sc1(String z) {System.out.println(z);} }
运行结果:开始练习
程序结束
3.对象的使用
格式:<对象名>.<变量名>
<对象名>.<方法名([参数])>
例:SC a =new SC( ) //SC是已定义的类,a则是新建的SC对象
a.bian=23 // 将对象a的变量bian赋值23
a.Fan( ) // 调用对象a的方法Fan
例:class parents{
private String name[]=new String[5];
parents(String s[])
{for(int i=0;i<s.length;i++)
name[i]=s[i]; }
public void showname()
{for(int i=0;i<s.length;i++)
System.out.print(name[i]+” ”);
}}
class SC
{ public static void main(String args[])
{ String name[]={"Zhang","Wang","Li"};
parents p=parents(name);
p.showname()
}}
结果: 输出 Zhang Wang Li
例:public class NewClass{
public static void main(String args[]){
G k=new G();
k.setK(8);
int y=k.getK();
System.out.println(“y=”+y); }
}}
class G{
private int k;
public void setK(int x){
k=x; }
public int getK(){ return k;}
}}
运行结果: y=8
4.清除对象
Java引入了新的内存管理机制,由Java虚拟机担当垃圾收集器的工作。你可以任意创建对象,而不用担心如何清除它们,垃圾收集器会自动清除它们。
如果要明确地清除一个对象,可以自行清除它。只需把一个空值赋给这个对象引用即可。如
SC a =new SC( )
……
a=null // 将对象a从内存中清除
5.析构方法(finalize)(补充)
析构方法(finalize)与构造方法相对应,当对象已经无用,需要清除时,编译器将自动调用对象的finalize方法。析构方法一般是做一些清除工作,如关闭打开的文件等,但不能执行用户输入操作或与其他对象进行交互。
如 class ABC{
……
protected|public void finalize( )
{ // do some cleanup code } }
4.3 成员变量与封装
成员变量描述了类和对象的状态,有时也称为属性、数据或域
4.3.1 成员变量的声明
成员变量的声明必须放在类体中,通常是在成员方法之前。在方法中声明的变量不是成员变量,而是方法的局部变量,二者是有区别的。
例:见P71
4.3.2 成员变量的修饰
声明变量格式:[public][private][protected][package] //访问控制修饰符
[static][final][transient][volatile]<数据类型><成员变量名称>
1.访问控制权限
表: 修饰符的作用范围
修饰符 | 类 | 子类 | 包 | 所有类和包 |
Public | √ | √ | √ | √ |
Private | √ | |||
Protected | √ | √ | √ | |
package(默认) | √ | √ |
(1)public(公共)变量
由public修饰的变量称为公共变量,可被任何包中的任何类访问
(2)private(私有)变量
由private修饰的变量称为私有变量,只能被声明它的类所使用
(3)protected(受保护)变量
由protected修饰的变量称为受保护变量,可被声明它的类和派生的子类以及同一个包中的类访问
(4)package(包)变量
由package修饰的变量称为包变量,没有修饰符时,默认变量即是包变量,可被声明它的类和同一个包中的其他类(包括派生子类)访问
2.static(静态)变量
由static修饰的变量称为静态变量,静态变量是类固有的,可以直接引用(方法:类名.静态变量名),其他成员变量仅仅被声明,只有等到生成实例对象后才存在,才可以被引用,静态变量也称为类变量,非静态变量称为实例变量。相应地静态方法称为类方法,非静态方法称为实例方法。
静态变量可被此类创建的所有对象共享。
例:class Car {
String 车型;
static int 价格;
public Car(String 车型, int 价格)
{ this.车型=车型;
this.价格=价格; }
public void 介绍(String s)
{System.out.println(s+"\t"+车型+"\t"+"价格 "+价格);} }
public class SC{
public static void main(String args[]){
Car 奔驰=new Car("越野车",400000) ;
奔驰.介绍("奔驰");
Car 红旗=new Car("轿车",200000) ;
红旗.介绍("红旗");
奔驰.介绍("奔驰"); }}
运行结果:奔驰 越野车 价格 400000
红旗 轿车 价格 200000
奔驰 越野车 价格 200000
3.final(最终)变量
一旦成员变量被声明为final,在程序运行中将不能被改变,即是一个常量。
如: final int I=5 ;
final double PI=3.1415926 ;
4.transient(过渡)变量(不做要求)
Java目前对transient修饰符没有明确说明,它一般用在对象序列化(object serialization)上,说明成员变量不许被序列化。
5.volatile(易失)变量(不做要求)
volatile声明的成员变量为易失变量,用来防止编译器对该成员进行某种优化。这是Java语言的高级特性,仅被少数程序员使用。
4.4 成员方法
对象的行为由类的方法实现,实际上,方法就是完成某种功能的程序块。从功能上讲,方法和函数十分类似。
4.4.1 成员方法的设计
例:见P77
4.4.2 成员方法的声明与修饰
格式:[public][private][protected][package][static][final][abstract][native]
[synchronized] 返回值类型 方法名(参数表)[throws 异常类型]
说明:[public][private][protected][package][static] [final]与成员变量功能相同,都是定义方法访问权限。
1.final(最终)方法
方法被声明为最终方法后,将不能被子类覆盖,即最终方法,能被子类继承和使用但不能在子类中修改或重新定义它。这种修饰可以保护一些重要的方法不被修改。
在OOP中,子类可以把父类的方法重新定义,使之具有新功能但又和父类的方法同名、同参数、同返回值,这种情况称为方法覆盖(override)。
2.abstract(抽象)方法
抽象方法即无方法体的方法,抽象方法不能出现在非抽象类中。
为什么要使用抽象类和抽象方法呢?一个抽象类可以定义一个统一的编程接口,使其子类表现出共同的状态和行为,但各自细节是不同的。子类共有的行为由抽象类中的抽象方法来约束,而子类行为的具体细节则通过抽象方法的覆盖来实现。这种机制可增加编程的灵活性,也是OOP继承树的衍生基础。
3.native(本地)方法(不做要求)
用其他语言编写的方法在Java中称为本地方法。
SDK提供了Java本地接口JNI(Java Native Interface),使得Java虚拟机能运行嵌入在Java程序中的其他语言,这些语言包括C/C++ ,FORTRAN ,汇编语言等。
4.synchronized(同步)方法
同步方法用于多线程编程。多线程在运行时,要能会同时存取一个数据。为避免数据的不一致性,应将方法声明为同步方法,对数据进行加锁。
5.throws(异常)类型
程序在运行时可能发生异常现象。每一个异常对象都对应着一个异常类,如果暂时不希望方法处理某种异常,可将其抛出,使程序得以继续运行。
如:protected void SC( ) throws IOException ; //输入输出异常抛出
6.返回值类型
Java要求一个方法必须声明它的返回值类型,如果方法没有返回值就用关键字void作为返回值类型。否则应使用基本数据类型或对象类型说明返回值类型。
如: public void SC( ) ; // 没有返回值
int getx( ) ; // 返回值是int类型
private String abc( ) ; // 返回值是String类型
public static double du( ) ; // 返回值是double类型
protected Object oj( ) ; // 返回值是Object类型
7.方法名
方法名要以是任何有效的Java标识符,方法名可以和成员变量同名,也可以和成员方法同名。同一个类中的方法同名现象在OOP中称为方法重载(overload)。
如: void SC( ) {……}
void SC(int a ) {……}
void SC(int a, int b) {……}
void SC(double a, int b) {……}
8.参数表
方法的调用者正是通过参数表将外部消息传递给方法的。在参数表中要声明参数的类型,并用逗号分隔多个参数。
4.4.3 方法体
方法体包含在一对大括号中,即使方法体中没有语句,一对大括号也是必不可少的。
4.4.4 消息传递
一个对象和外部交换信息主要靠方法的参数来传递,如果允许的话,外部对象也可以直接存取一个对象的成员变量。
在Java中调用方法时,如果传递的参数是基本数据类型,在方法中将不能改变参数的值,你只能使用它们。如果传递的是对象引用,你也不能在方法中修改这个引用,但可以调用对象的方法以及修改允许存取的成员变量。所以想改变参数的值,可采用传递对象的方法,间接修改参数的值。
例1:class SC{
public static void main(String[] args){
int m=10, n=20 ;
Power p=new Power( ) ;
p.doPower(m , n);
System.out.println("x="+m+",y="+n);
System.out.println("x="+p.x+",y="+p.y) ; } }
class Power{
int x , y ;
void doPower(int a , int b)
{ x=a*a ;
y=b*b ; } }
运行结果:x=10,y=20
x=100,y=400
例2:class SC{
float ptValue ; //成员变量
public static void main(String[] args){
int val=11 ; // 局部变量
SC pt=new SC( ) ;
System.out.println("val1="+val) ;
pt.changeInt(val) ;
System.out.println("val2="+val) ;
pt.ptValue=101f ; //float类型,加f
System.out.println("valValue1="+pt.ptValue) ;
pt.ChangeObj(pt) ;
System.out.println("valValue2="+pt.ptValue) ; }
public void changeInt(int value) //参数是简单类型
{value=55 ; }
public void ChangeObj(SC ref)//参数是对象引用类型
{ref.ptValue=99f ; }
}
运行结果:val1=11
val2=11
valValue1=101.0
valValue2=99.0
作业:P87-16 class Rectangle {
double width,height;
double zc(double b1,double b2)
{ return 2*(b1+b2); }
double mj(double b1,double b2)
{ return b1*b2; }}
public class SC{
public static void main(String args[]){
Rectangle r=new Rectangle();
r.width=10 ; r.height=20;
System.out.println("周长="+r.zc(r.width,r.height)) ;
System.out.println("面积="+r.mj(r.width,r.height)) ; }}
作业:P87-17 public class SC{
public static void main(String args[]) {
int m[]={1,2,3,4,5};
Array A=new Array(m);
A.sum( );
System.out.println(A.getsum()); }}
class Array{
private int n[];
int sum=0;
Array(int i[]) { n=i; }
void sum( ){
for (int x=0;x<n.length;x++)
sum=sum+n[x] ; }
int getsum( ){
return sum; } }
第5章 类的继承性与多态性
OOP的特点:继承、封装、多态、抽象
5.1 类的继承
在Java中,许多类组成层次化结构,一个类的上一层称为父类,而下一层称为子类。一个类要以继承其父类的变量和方法,继承特性使Java既灵活方便又能提高效率。
5.1.1 父类和子类
被继承的类称为父类或超类,这个新类称为子类。
子类的创建格式: [<修饰符>] class <子类名> extends <父类名>
{ ………… }
例:public class Hello2 extends java.applet.Applet
public class SC extends Object // extends Object 可以省略
说明:从Java系统软件包java.lang中的Object派生来的子类可以不指出父类的名字,一般称这些类的父类为隐含类。
5.1.2 成员变量的继承和隐藏
1.成员变量的继承
继承原则:
(1)子类不能继承父类的private成员变量
(2)子类能继承父类的public和protected成员变量
(3)子类能继承同一包中有默认权限修饰符的成员变量
2.成员变量的隐藏
隐藏原则:子类的成员变量和父类的成员变量同名,父类的成员变量被隐藏(不能继承)
5.1.3 成员方法的覆盖
继承原则:
(1)子类不能继承父类的private成员方法
(2)子类不能继承父类的构造方法
(3)子类能继承父类的public和protected成员方法
(4)子类能继承同一包中有默认权限修饰符的成员方法
覆盖(隐藏)(override)原则:
子类的成员方法和父类的成员方法同名,父类的成员方法被覆盖(隐藏)(不能继承)
说明:(1)用来覆盖的子类方法应和被覆盖的父类方法保持相同名称和相同返回值类型,以及相同的参数个数和参数类型。
(2)可能不需要完全覆盖一个方法,部分覆盖是在原方法的基础上添加新的功能,即在子类的覆盖方法中添加一条语句:super.原父类方法名,然后加入其他语句
(3)不能覆盖父类中的final方法
(4)不能覆盖父类中的static方法,但可以隐藏这类方法。即在子类中声明的同名静态方法实际上隐藏了父类中的静态方法
(5)非抽象子类必须覆盖父类中的抽象方法
5.1.4 this和super
调用本类成员和方法格式:
this.变量名 this.方法名([参数])
调用父类成员和方法格式:
super.变量名 super.方法名([参数])
调用本类构造方法:
this([参数列表])
调用父类构造方法:
super([参数列表])
(1)this代表当前类或对象本身
例: class Tree {
int h , s , b ; //成员变量
Tree(int h , int s , int b)
{ this.h=h ; // this.h为成员变量的h, 右边h是入口参数h
this.s=s ; this.b=b ; } }
(2)super代表父类
例: public class SC
{ public static void main(String args[])
{ Son a=new Son();
a.ClearUp(); }
public void ClearUp( )
{ System.out.println("开始打扫"); } }
class Son extends SC{
Son(){System.out.println("今天是周末");}
public void ClearUp()
{ super.ClearUp( );
System.out.println("已清扫干净!"); } }
运行结果: 今天是周末
开始打扫
已清扫干净!
说明:不需要实例化父类就可以直接使用super变量
(3)super()可用来调用父类的构造方法
Java规定类的构造方法只能由new调用,程序员不能直接调用,但可用super( )间接调用,同理this( )也可间接调用当前类或对象的构造方法
类的构造方法是不能继承的,因为构造方法不是类的成员,没有返回值,也不需要修饰符。
说明:super( )只能出现在子类的构造方法中,而且必须是子类构造方法中的第一条可执行语句。
5.2 类的多态
在一个类中,可以定义多个同名的方法,只要确定它们的参数个数和类型不同,这种现象称为类的多态
类的多态性体现在方法的重载上,包括成员方法和构造方法的重载
5.2.1 成员方法的重载
方法的重载是指对同名方法的重新定义
例: public void fun(int a)
public void fun(int a , int b)
public void fun(int a , float b , String s)
public int fun(int a) //不是正确的重载
例: public class SC
{ public double area(float a) //改成int area(float a)将报错
{return (int)(Math.PI*a*a*100)/100.0 ;} //保留2位小数
public double area(float a, float b)
{return a*b ;}
public double area(float a, float b, float c)
{float d;
d=(a+b+c)/2 ;
return Math.sqrt(d*(d-a)*(d-b)*(d-c)) ;}
public static void main(String args[])
{ SC sh=new SC();
System.out.println("圆面积是: "+sh.area(3));
System.out.println("矩形面积是: "+sh.area(7,4));
System.out.println("三角形面积是: "+sh.area(3,4,5)); } }
运行结果:圆面积是: 28.27
矩形面积是: 28.0
三角形面积是: 6.0
例:见P96
5.2.2 构造方法的重载
例: class Date( ) {
Date( ) {……}
Date(int x, int y ) {……}
Date(int x, char y ) {……}
}
…………
Date d1=new Date( )
Date d2=new Date(5,’A’ )
Date d3=new Date(5,12) //分加调用不同的构造方法
作业P101 5-11
class Fraction{
private int f1,f2;
Fraction(int x,int y)
{f1=x;f2=y;}
void Xc(int i1,int i2,int i3,int i4)
{f1=i1*i3;
f2=i2*i4;}
void Dy1()
{System.out.println(f1+"/"+f2);}
void Dy2()
{System.out.println((double)f1/(double)f2);}}
public class SC{
public static void main(String arg[]){
Fraction a=new Fraction(0,0);
a.Xc(4,5,7,3);
a.Dy1();a.Dy2();} }
第6章 包、接口和异常
包(package)是类和接口的集合,利用包可以把常用的类或功能相似的类放在一个包中。Java还提供了系统包。
接口(interface)解决了Java不支持多重继承的问题,可以通过实现多个接口达到与多重继承相同的功能。
6.1 包
包是Java提供的一种区别类名空间的机制,是类的逻辑组织形式,一个包对应一个文件夹,包中还可以有包,称为包等级。
当源程序中没有声明类所在的包时,Java将类放在默认包中,即运行编译器的当前文件夹中。这时不能出现重复的类名。
6.1.1 Java的系统包
Java提供了大量的类,为便于管理和使用,分为不同的包。这些包又称类库或API包,所谓API(application program interface)即应用程序接口。API包一方面提供丰富的类与方法供大家使用,如画图形、播放声音等,另一方面又负责和系统软硬件打交道,把用户程序的功能圆满实现。
许多Java API包都以“java.”开头,以区别用户创建的包。
1.java.lang
是Java语言的基础类库,包含基本数据类型、数学函数、字符串等。这是唯一自动引入每个Java程序的类库。Java.lang包中包含有以下主要类:
(1)Object 类:是Java类层次的根,所有其他类都是由Object类派生出来的。其定义的方法,在其他类中都能使用。如:复制方法clone( ),获得对象的类getClass( )方法,两个对象是否相等的equals( )方法,将对象输出为字符串的toString( )方法等
在比较两个变量、两个值、对象与变量相等时使用“==”,在比较两个对象相等时使用equals()
char ch='a' ;if(ch=='a'||ch=='A');
String S1="123" ,S2="123" ;
if(S1==S2)
System.out.println(S1.equals(S2)); // 与S1= =S2效果一样,true
System.out.println(ch.equals(S2)); //错
(2)数据类型包装类:
(3)数学Math类:如常数E和PI,数学方法sin和cos等,Math是最终类,其中的数据和方法都是静态的(直接用类名引用)
(4)字符串String和StringBuffer类
(5)系统System类:提供访问系统资源和标准输入输出方法
如:System.out.print (<输出量>)
System.exit(0) // 结束当前程序的运行
System类的变量和方法都是final和static
(6)运行时Runtime类:可以直接访问运行时的资源
如:totalMemory方法可返回系统内存总量
freeMemory方法返回内存剩余空间
(7)线程Thread类
(8)类操作class和classLoader类:
如: this.getClass( ).getName( ) // 返回当前对象的类名
(9)错误和异常处理类:Throwable , Exception , Error
2.java.util包
提供了实现各种低级实用功能的类,如日期类、集合类等
(1)Date类:构造方法Date()可获得系统当前日期和时间
(2)Calender类:将Date对象的数据转换成YEAR , MONTH , DATE , DATE_OF_WEEK等常量,Calender类没有构造方法,可用getInstance方法创建一个实例,再调用get方法和常量获得日期或时间的部分值。
如:Calender now=Calender.getInstance( ); // 创建类Calendar的实例,并获得系统日期和时间
int year=now.get(Calender.YEAR) ; // 用get方法得到当前年份
GregorianCalendar类是Calender类的子类,实现标准的Gregorian日历
(3)随机数Random类
3.java.io包
是Java语言的输入输出类库,Java语言的文件操作都是由该类库中的输入输出类(FileInputStream和FileOutputStream)实现的,java.io包除了包含标准输入、输出类外,还有缓存流、过滤流、管道流和字符串类等
4.java.net包
支持TCP/IP网络协议,并包含Socket类及URL和URL相联系的类
5.java.awt包
提供了创建图形用户界面的全部工具。如:窗口、对话框、按钮、复选框、列表、菜单、滚动条和文本区等类;用于管理组件排列的布局管理器类Layout;以及常用颜色类Color、字体类Font。Java.awt.event类库用来处理各种不同类型的事件。
6.java.applet包
是所有小应用程序的基础类库。它只包含了一个Applet类和三个接口AppletContext , AppletStub , AudioClip,所有小应用程序都是从该类中派生的。
7.java.security包
包括java.security.acl和java.security.interfaces子类库,利用这些类可对Java程序进行加密,设定相应的安全权限等。
6.1.2 包的引用
1.导入包语句
格式:import <包名1>[.<包名2>……] .<类名>|* ;
说明:如果有多个包或类,用“.”分割,“*”表示包中所有的类。
例: import java.applet.Applet // 导入java.applet包中的Applet类
import java.awt.* // 导入java.awt包中的所有类
java.lang包是系统自动隐含导入
2.包的路径
由于Java使用文件系统来存储包和类,类名就是文件名,包名就是文件夹名,设置环境变量用classpath方法
6.1.2 声明自定义包
1.创建自定义包
格式: package <包名>
说明:(1)声明包语句必须添加在源程序的第一行,表示该文件的全部类都属于这个包
(2)可以在不同的文件中使用相同的声明语句,可将不同文件中的类都包含在相同的包中
(3)若在程序中没有声明包,类就放在默认的包中,这个包没有名字,默认包适用于小的程序。
例:见P108 YMD.java文件内容:
package Mypackage; // 声明一个Mypackage包,区分大小写
import java.util.*;
public class YMD{
private int year,month,day;
public static void main(String []args) {}
public YMD(int y, int m ,int d){
year=y;
month=(((m>=1)&(m<=12))?m:1);
day=(((d>=1) & (d<=31))?d:1); }
public YMD(){
this(0,0,0); }
public static int thisyear(){
return Calendar.getInstance().get(Calendar.YEAR); }//获得当年的年份
public int year(){
return year; }
public String toString(){
return year+"-"+month+"-"+day; //转化为字符串
}}
说明:建立Mypackage(区分大小写)文件夹,并将YMD.class复制该文件夹下
*******************************************
P3.java文件内容:
import Mypackage.YMD;
public class P3{
private String name;
private YMD birth;
public static void main(String args[]){
P3 a=new P3("张弛",1990,1,11);
a.output();}
public P3(String n1,YMD d1){
name=n1;
birth=d1; }
public P3(String n1,int y,int m,int d){
this(n1,new YMD(y,m,d)); //初始化变量与对象,调用上一个构造方法}
public int age()
{return YMD.thisyear()-birth.year(); //计算年龄 }
public void output(){
System.out.println("姓名: "+name);
System.out.println("出生年龄: "+birth.toString());
System.out.println("今年年龄: "+age());
}}
2.设置包的路径
用自定义包名建立一个文件夹,如:c:\ Mypackage
设置路径:set classpath=. ; c:\j2sdk1.4.2 ; c:\mypackage
以后其它类使用自定义包里的类用命令:import Mypackage.*
3.创建包等级
格式: package <包名1>[.<包名2>][.<包名3>][.<……>]
4.包的访问权限
同一个类中 | 同一个包中 | 不同包中的子类 | 不同包中的非子类 | |
private | √ | |||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
friendly | √ | √ |
5.编译和运行包(补充)
例:package p1;
public class SC{
public static void main(String args[]){
System.out.println("演习!"); }}
操作要求::
(1)编译文件方法一:javac SC.java
(2)新建p1文件夹,将SC.class存入其中;
(3)在p1文件夹的上一级文件夹中运行 java p1.SC
说明:因为SC.class存在p1包中,对它的引用应是: p1.SC.class,所以在p1目录下运行java SC则错,java p1.SC也错,必须退到上一级,运行java p1.SC才正确。
编译文件方法二:javac –d . SC.java
系统行动在当前文件夹(.)下新建p1文件夹,且将SC.class自制到p1文件夹下
6.2 接口
与C++语言不同,Java语言不支持多重继承,为了实现多重继承的功能,Java提供接口来实现,且比多重继承具有更强的功能。
多重继承指一个类可以是多个类的子类
接口可以看作是没有实现的方法和常量的集合。接口与抽象类相似,接口中的方法只是做了声明,而没有定义任何具体的操作方法。
接口功能:
(1)通过接口可以实现不相关类的相同行为,而不需要考虑这些类之间的层次关系
(2)通过接口可以指明多个类需要实现的方法
(3)通过接口可以了解对象的交互界面,而不需了解对象所对应的类。
6.2.1 实现系统提供的接口
接口中定义的变量全部隐含为了final和static,表明这些变量不能被实现接口方法的类改变,这些变量还必须设置初值。如果接口为public,则接口中的方法和变量也全部为public,否则只能被处于同一包中的成员访问。
类引用接口不叫继承而称为实现。
系统接口,如MouseListener和MouseMotionListener接口,定义了处理鼠标事件的方法。
格式: class <类名> implements <接口名>[,<接口名>]
例:P110
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class SC 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){ //习惯写成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){ }
}
说明:在实现接口时,要实现所有接口中定义的所有方法,方法的实现要以具有具体的实现内容,也可以是空的方法,即只有方法名或参数,没有变量、没有具体操作语句
6.2.2 创建自定义接口
格式:[修饰符] <interface> <接口名>
{ 静态常量及方法声明 }
说明:(1)Java系统会自动把接口中声明的变量当作static final类型,不管是否使用了这些修饰符,且必须赋初值,这些变量值都不能被修改。
(2)接口中的方法默认为abstract,不管有没有这些修饰符。
(3)接口若是public,那么该接口可被任意类实现,否则只有与接口在同一个包中类的实现。
(4)接口若为public,则接口中的变量也是public。
例:interface Colle{
int Max_Num=100;
void add(Object obj);
void delete(Object obj);
Object find(Object obj);
int currentCount( ); }
}
例:见P112
6.2.3 接口的继承关系(自学)
1.接口的单继承
接口之间的继承与类的继承一样使用extends
格式: interface <新接口名> extends <已有接口名>
例:见P113
如果一个类实现了接口B,那么它必须实现接口A和接口B中的全部方法。
2.接口的多重继承
在Java语言中,不支持类的多重继承,但支持接口的多重继承
格式: interface <新接口名> extends <已有接口名1>[<,接口名2>…]
注意:引用接口时,必须实现接口中的所有方法。
6.3 异常处理
错误分编译错误和运行错误。编译错误主要是程序中的语法错误,可以在程序编译过程中发现。而而运行错误就复杂得多,有些只在程序运行过程中才会暴露出来。
Java语言的错误处理机制—异常处理,可以监视某段代码是否有错,并且将各种错误集中处理。
以往需要由程序员完成的程序出错情况判别,在Java中改为由系统承担
6.3.1 什么是错误与异常
运行错误分致命错误和异常两种类型
1.致命性错误
如死循环或内存溢出,运行时程序本身无法解决,只能依靠其他程序干预,否则会一直处于不正常状态。
2.异常
如除数为0,操作数超出数据范围,打开文件不存在等
6.3.2 异常发生的原因
(1)Java虚拟机检测到了非正常的执行状态,这些状态可能是由以下几种情况引起的:
- 表达式的计算违反了Java语言的语义,例如整数除数为0
- 在载入或链接Java程序时出错
- 超出了某些资源限制,例如使用了太多的内存
这些异常都是无法预知的。
(2)Java程序代码中的throw语句被执行
(3)异步异常发生:
- Thread的stop方法被调用
- Java虚拟机内部错误发生
6.3.3 异常处理机制
1.抛出异常
当发生异常时将会抛出(throw)异常,即产生一个异常事件,生成一个异常对象,并把它提交给运行系统,再由系统找相应的代码来处理异常。一个异常对象可以由Java虚拟机产生,也可以由运行的方法生成。异常对象中包含了异常事件类型、程序运行状态等必要信息。
2.捕获异常
异常抛出后,运行时系统从生成异常对象的代码开始,没方法的调用栈进行查找,直到找到包含相应处理的方法代码,并把异常对象交给该方法为止,这个过程称为捕获(catch)异常。
简单说异常处理机制:当语义限制被违反时,将会抛出异常对象,并将引导程序流程从异常发生点转移到程序员指定的处理异常方法代码处进行异常处理。
6.3.4 异常对象类型(补)
异常类都是Throwable的子类,一般说程序不捕获也不抛出类Error的对象(包括动态链接失败、虚拟机错误等),而只处理Exception类的各子类对象
java.lang.Objectàjava.lang.Throwableàjava.lang.Error
àjava.lang.Exception
àjava.lang.RuntimeException
àjava.lang.IOException
参见P116
6.3.5 异常的处理
格式: try {……} // 被监视的代码段
catch(异常类型1 e) // 要处理的第一种异常
catch(异常类型2 e) // 可以不写成e
…………
finally {……} //最终处理
对异常进行处理时,一般是把可能会发生异常情况的代码放在try语句段中,利用try语句对这组代码进行监视。发果发生了第一种异常,使用第一个catch中的代码段处理;如果发生了第二种异常,则使用第二个catch代码段处理。
如果希望在异常发生时能确保有一段代码被执行,那么应该使用finally子句。
catch语句在执行前,必须识别抛出的异常对象类型是catch能够捕获的“异常类”如果catch语句参数中声明的异常类与抛出的异常类相同,或者是它的父类,catch语句就可以捕获任何这种异常类的对象。e为相应的异常对象。
例6.5 :见P115
如果不能确定会发生哪种情况的异常,那么最好指定catch的参数为Exception,即说明异常的类型为Exception。
例6.6 :见P116
捕获例外的顺序是和不同catch语句的顺序相关的,因此在安排catch语句顺序时,首先应该捕获最特殊的例外,然后再逐渐一般化,如果一个异常类和其子类都出现在catch子句中,应把子类放在前面,否则将永远不会到达子类。另如果catch语句所捕获的例外类型不是一个“终极”类型(即它还有子类),则一个catch语句可以同时捕获多种例外。
例:P117
例:public class SC{
int count =1;
public static void main(String args[])
{SC abc=new SC();}
public SC( ){
while(true){
try{ int x=6/(count--);
System.out.println("in try,no exception") ; }
catch(ArithmeticException e)
{ System.out.println("in catch,divided by zero");}
finally{
System.out.println("in finally");
if (count==-1) break; }
} System.out.println("end of program"); } }
运行结果:in try,no exception
in finally
in catch,divided by zero
in finally
end of program
6.3.6 throw语句
异常对象可以是Java系统抛出的。也可以通过代码实现,使用throw语句就可以明确抛出一个异常。
格式:throw <异常对象>
如:IOException e new IOException( ) ;
throw e;
例:P118
6.3.7 throws子句
throws用来表明一个方法可能抛出的各种异常,并说明该方法会抛出但不捕获异常。
1.抛出异常的方法(自学)
2.调用方法处理异常(自学)
3.由方法抛出异常交系统处理
对于程序中需要处理的异常,一般编写try-catch-finally语句捕获处理,而对于程序中无法处理必须由系统处理的异常,可以使用throws语句在方法中抛出异常交由系统处理。
格式:返回类型 方法名(参数表) throws 异常类型表
例:P123
例:public int read( ) throws IOException{……}
说明:(1)该方法将不对这些例外进行处理,而是声明抛弃它们。
(2)对于非运行时例外,如前IOException等,程序中必须要作出处理,或者捕获,或声明抛弃。而对于运行时例外,如ArithmeticException, IndexOutOfBoundsException,则可以不做处理。
6.3.8 finally语句
每个try语句至少要有一个与之相匹配的catch或finally子句。
例:P121
finally子句总是在方法返回前执行
6.3.9 编译时对异常情况的检查
1.可检测的异常
在编译时,编译器将分析哪些方法会产生可检测的异常,然后检查方法中的可检测异常的处理部分。如果方法中没有异常处理部分,就要在方法的throws子句说明该方法会抛出但不捕获的异常,以告知调用它的其他方法,即将异常上交给调用者处理。
如果程序在运行的过程中抛出异常,而这个异常是可检测的,则在程序中必须捕获这个异常进行处理或声明抛弃(throws)该异常,捕获异常可以使用try语句,而抛弃异常在方法声明时声明,即在方法声明后加上throws xxxException子句,抛弃外个异常时可在各异常间使用“,”分隔。
例P123:
import java.io.*;
public class SC{
public static void main(String a[]) throws IOException {
//省略throws IOException 编译时即报错
FileInputStream fis=new FileInputStream("a2.txt"); }}
2.不可检测的异常(运行时异常类)
不可检测的异常类是RuntimeException及其子类、Error及其子类,其他异常类则是可检测的类。编译器对不可检测的异常类不进行检查。
解释器在执行程序时会对出现异常的程序给出异常报告。
6.3.10 创建自己的异常类(自学)
格式:<class> <自定义异常名> <extends> < Exception>{……}
在使用各种例外类型时,建议:
(1)对于运行时例外,如果不能预测它何时发生,程序可以不做处理,而是让虚拟机处理它。
(2)如果程序可以预知运行时例外可以发生的地点和时间,则应该在程序中进行处理,而不应简单地把它交给运行时系统。
(3)在自定义例外类时,如果它所对应的异常事件通常总是在运行时产生的,而且不容易预测它将在何时、何处发生,则可以把它定义为运行时例外,否则应定义为非运行时例外。
使用异常处理准则:
(1)尽可能在当前程序中解决问题,否则应将异常向更外层的程序抛出。
(2)简化编码,不要因加入异常处理而使程序变得复杂难懂。
第7章 常用系统类
7.1 Applet类
Applet是种特殊的Java程序,经过编译后可被嵌入到HTML文件中,并由Web浏览器内置的Java解释器执行。所有Applet都继承自同一个类java.appelt.Applet,这个类是Java语言的基础类,有关Applet的所有特性都被定义在这个类中。
7.1.1 Applet的特点
Applet | Application | |
运行环境 | 在浏览器中运行,或用appletviewer命令 | 单独运行 |
入口 | 从init( )方法开始 | 从main( )开始 |
来源 | 从网上来 | 放在本地 |
出于安全考虑,Java设计者对Applet做了一些必要的限制。P129
有关Applet的安全机制通常被设置在浏览器中。大多数浏览器都会禁止Applet执行下列操作:
(1)在运行时调用其他程序
(2)文件读写操作
(3)装载动态连接库和调用任何本地方法
(4)试图打开一个socket进行网络通信,但是所连接的主机并不是提供Applet的主机。
另一方面,java.applet包提供了Application所不具备的一些API接口。
7.1.2 Applet和HTML的关系
HTML可以没有Applet,但很多重要功能将无法实现,而Applet有赖于HTML才能运行,二者共同为Internet这个虚拟世界增添光彩。
7.1.3 Applet的生命周期与主要活动
例P131 import java.applet.Applet;
import java.awt.Graphics;
public class SC extends Applet{
StringBuffer buffer=new StringBuffer();
public void init( ) {addWords("初始化……");} //与位置顺序无关
public void start( ) {addWords("开始……");} //与位置顺序无关
public void stop( ) {addWords("停止……");} //关闭窗口后执行
public void destroy( ) {addWords("清除……");} //关闭窗口后执行
void addWords(String s)
{System.out.println(s); //在DOS界面显示
buffer.append(s);
repaint();} //自动调用paint方法
public void paint(Graphic s g) {
g.drawString(buffer.toString(),5,15);}} //在图形界面显示内容
1.初始化(init)
当Applet首次加载(或重新加载)时,要进行初始化操作。初始化可进行建立添加到程序中的对象、设置对象初始状态、为成员变量赋初值、加载图像或字体等操作,这些可通过覆盖init方法来实现。
当然程序也可以没有init方法。
2.开始运行(start)
Applet在初始化完成后即被调用,如果运行已被停止,还可以再次启动。尽管在一个生命周期中,Applet可以多次开始运行,但初始化只能进行一次。
start方法可以在下列情况下自动执行多次:
- 浏览器载入小应用程序并执行init( )之后;
- 离开上述Web页之后,又重新回来时;(用back后退,forword前进按钮)
- 浏览器的窗口最小化后又恢复时。
在start方法中可以开始运行Applet的功能,也可以启动一个或多个线程来完成任务。一般情况下,如果覆盖了start方法就要覆盖stop方法
3.停止运行(stop)
stop方法可以在下列情况下自动执行多次:
- 离开小应用程序所在Web页时;(用back后退,forword前进按钮)
- 刷新该页面时;(重新reload该页面时)
- 关闭该Web页时;
- 最小化浏览器时。
4.清除(destory)
关闭该Web页时执行一次
5.画出(显示)(paint)
如果需要Applet显示一些内容的话,必须覆盖paint方法进行写屏。不论所显示的内容是文字、线条、背景色,还是一幅图形,都必须在paint方法中完成。
paint方法也是小应用程序执行时自动调用的方法,当下列情况下会发生paint方法的自动调用:
- 第一次加载含有小应用程序的Web时;
- Web页被覆盖后又重新显示时;
- 浏览器显示区域被缩小/放大时。
首先引用:import java.awt.Graphics
方法: public void paint(Graphics g){……}
6.刷新(repaint)
repaint方法:是小应用程序从java.awt.Component中继承来的方法,它首先激活update( )方法(也是在java.awt.Component中定义),清除显示区域的所有显示内容,再调用paint( )方法重绘显示区域。
7.1.4 HTML和Applet的参数传递
- 在网页中,必须使用<param>的标识来指定参数的名称和参数的内容值。格式:<param name=参数名 value=参数值>
- 在Applet程序中必须使用getParameter( )方法来取得参数的内容。格式:public String getParameter(“参数名”)
例:P133
import java.applet.Applet;
import java.awt.Graphics;
public class SC extends Applet{
String string=null;
int x,y;
public void init(){
string=getParameter("message");
x=Integer.parseInt(getParameter("xPos"));//写成(int)”30”错
y=Integer.parseInt(getParameter("yPos"));}//可以不用Integer.parseInt
public void paint(Graphics s){
if (string!=null)
s.drawString(string,x,y);
s.drawString("参数X为: "+x,30,60);
s.drawString("参数Y为: "+y,30,90);}}
7.1.5 Applet标签属性
参见P135
7.2 字符串类
在Java中字符串被定义为一个类,无论是字符串常量还是变量,都必须先生成St ring类的实例对象然后才能使用。
包java.lang中封装了两个字符串类String(java.lang.String)和StringBuffer,分别用于处理不变字符串和可变字符串。这两个类都被声明为final。因此不能被继承
7.2.1 字符串与字符串类
用双引号括起来的字符串是字符串常量,又称为无名字符串对象,由Java自动创建。
例:P137
说明:s.charAt(i) //返回字符串的第i个字符
buffer.append(char a) // 将字符参数添加到对象buffer尾部
buffer.toString( ) //将StringBuffer类型转换成String类型再返回。
7.2.2 字符串类的构造方法
例P139
import java.io.*;
import java.applet.Applet;
import java.awt.Graphics;
public class SC extends Applet{
byte b[]={'A',' ','b','y','t',' ','a','r','r','a','y'};
char c[]={'A',' ','c','h','a','r',' ','r','r','a','y'};
String s1,s2,s3,s4,s5,s6,s7,s8,s9;
StringBuffer b1,b2,b3;
public void init(){
b1=new StringBuffer();
b2=new StringBuffer(10);
b3=new StringBuffer("A string buffer");//写成b3="A string buffer"错
s1=new String();
s2=new String("A string"); // 写成s2="A string" 对
s3=new String(b3); // 写成s3=b3;错
s4=new String(b);
s5=new String(b,2,4);
try{
s6=new String(b,2,10,"GBK");
s7=new String(b,"GBK");
}catch (UnsupportedEncodingException e) {}
s8=new String(c);
s9=new String(c,2,4);}
public void paint(Graphics g)
{ g.drawString("s1="+s1,20,20);
g.drawString("s2="+s2,20,35);
g.drawString("s3="+s3,20,50);
g.drawString("s4="+s4,20,65);
g.drawString("s5="+s5,20,80);
g.drawString("s6="+s6,20,95);
g.drawString("s7="+s7,150,20);
g.drawString("s8="+s8,150,35);
g.drawString("s9="+s9,150,50);
g.drawString("b1="+b1.toString(),150,65);
g.drawString("b2="+b2.toString(),150,80);
g.drawString("b3="+b3.toString(),150,95); } }
7.2.3 String类的应用
1.求字符串长度(length)
格式:public int length( )
例:System.out.println("管理学院".length( )); // 4
System.out.println("GLXY".length( )); // 4 "GLXY".length( )则错
char c[]={'G','L','X','Y'};
System.out.println(c.length); // 4 ,c.length( )则错
2.字符串连接
格式:public String concat(String str )
例: String str="hello";
str=str.concat("Hi"); // 与 str+”Hi” 等价
System.out.println(str); // helloHi
别:“+”还可以把一个非字符串的数值连接至字符串尾部,编译器将自动把非字符串转换为字符串再进行连接。
3.字符串截取
格式:public char charAt(int index)
功能:返回第index个字符
格式:public String substring(int start [int end])
功能:从第start开始截取字符串,end代表结束位置
例: String s1="安徽城管学院",s2=s1;
System.out.println(s1.charAt(2)); // 城
s1=s1.substring(2);
System.out.println(s1); // 城管学院
System.out.println(s2.substring(2,4)); // 城管
4.字符串比较
格式: boolean equals(Object object)
boolean equalsIgnoreCase(String str) // 忽略大小写
int compareTo(Object object)
int compareTo(String str)
int compareToIgnoreCase(String str) // 忽略大小写
例: String s1="ABCD",s2="ABC",s3="abc";
System.out.println(s1.equals(s2)); // false
System.out.println(s2.equals(s3)); // false
System.out.println(s2.equalsIgnoreCase(s3)); // true
System.out.println("A".compareTo("B")); // -1 “A”比“B”小
System.out.println("B".compareTo("A")); // 1“B”比“A”大
System.out.println("ABC".compareTo("abc")); //-32 小,是负数
System.out.println("ABC".compareToIgnoreCase("abc"));//0 相同
说明:运算符“==”比较两个对象是否引用同一个实例,而equals( )则比较两个字符串中对应的每个字符值是否相同。
例: Sting a=”ABC” ,B=”ABC” ,C=”abc” ,D=”AB”
A==B // true
A==C // false
A==D // false
5.拷贝到字符串
格式1:static String copyValueOf(char[] data)
格式2:static String copyValueOf(char[] data ,int offset ,int count)
功能:将字符数组的内容拷贝到字符串中
例:char c[]={'A','B','C','D','E'};
String s1="XYZ",s2=s1;
s1=s1.copyValueOf(c); // s1值是“ABCDE”
s2=s2.copyValueOf(c,1,3); // s2值是“BCD”
s3=substring(c,3); // 错
s3=c; // 错
Sting s1= new String(c)
Sting s1= new String(c,2,3)
6.字符串大小写转换
例:String s1="Abc",s2,s3;
s2=s1.toUpperCase( ); // s2值是“ABC”
s3=s1.toLowerCase( ); // s3值是“abc”
7.字符串检索
格式:int indexOf(char ch) // 首次出现位置
int indexOf(String str)
int lastIndexOf(char ch) // 最后出现的位置
int lastIndexOf(String str)
功能:在一个字符串中检索指定字符或子串,返回所在位置的整数,若找不到则返回为-1。
例:String s1="ABABab";
System.out.println(s1.indexOf('a')); // 4
System.out.println(s1.indexOf("AB")); // 0
System.out.println(s1.lastIndexOf('A')); // 2
8.字符串转换为数组
字符串可以转换为字节数组或字符数组。
格式:byte []getBytes( ) //按系统默认字符集编码转换为字节数组
byte []getBytes(String enc ) //基中enc为字符集编码
char []toCharArray( ) // 转换为字符数组
例: byte b[]; char c[];
String s="计算机";
b=s.getBytes();
c=s.toCharArray();
System.out.println(b); // [B@17943a4
System.out.println(c); // 计算机
9.转换为字符串
String类提供了一组valueOf方法用来将其他数据类型转换成字符串,其参数可以是任何数据类型(byte类型除外),它们都是静态的,也就是说不必创建实例化对象即可直接调用这些方法。
格式: String.valueOf(数据类型)
例:char c[]={'A','B','C','D','E'};
String s="Help",s1,s2,s3;
s1=String.valueOf(c,1,3); // “BCD”
s2=String.valueOf(true); // “true”
s3=String.valueOf(95.5); // “95.5”
同时,类Integer,Double,Float和Long中也提供了方法valueOf( )把一个字符串转化为对应的数字类型。
例:String s="35";
Integer i=Integer.valueOf(s); // 35
Double d=Double.valueOf(s); // 35.0
10.字符串替换(补充)
格式:public String replace(char oldChar ,char newChar)
功能:把字符串中出现的所有指定字符转换成新字符
例:String s1="ABACAD",s2;
s2=s1.replace('A','Z'); // “ZBZCZD”
7.2.4 StringBuffer类的应用
StringBuffer表示可变字符串,可以在其中插入字符或在末尾添加字符。如果超出已分配的缓冲区,系统会自动地为它分配额外空间。
1.append方法
格式:public synchronized StringBuffer append(数据)
功能:在已有字符串末尾添加一个字符串str
例:P144 char data[]={'a','b','c','d','e'};
StringBuffer buffer=new StringBuffer();
buffer.append(100);
buffer.append('*');
buffer.append(2.50F);
buffer.append(" is equal to ");
buffer.append(250.000);
buffer.append(' ');
buffer.append(data);
buffer.append(' ');
buffer.append(data,2,3);
System.out.print(buffer);
运行结果:100*2.5 is equal to 250.0 abcde cde
String s=”ab”;
StringBuffer b=”XYZ”; //错
StringBuffer b=new StringBuffer(“XYZ”);
s=b ; // 错
s=b.toSting() // “XYZ”
b=s; //错
int i=b.length();
b=b.replace(0,s); //将字符串s值给bs
2.insert方法
格式:public synchronized StringBuffer insert(插入位置,数据)
功能:在插入位置处插入数据,总长度增加
例P144 char data[]={'a','b','c','d','e'};
StringBuffer buffer=new StringBuffer();
buffer.insert(0,100);
buffer.insert(0,2.5F);
buffer.insert(3,'*');
buffer.insert(0,250.0);
buffer.insert(5," is equal to ");
System.out.print(buffer);
运行结果:250.0 is equal to 2.5*100
3.其他方法
public StringBuffer delete(int start ,int end) //删除子串,不包括end位字符
public StringBuffer deleteCharAt(int index) //删除index位置上的字符
public StringBuffer replace(int start,int end,String str) //替换子串,字符串长度可增长或减短
StringBuffer reverse( ) //翻转字符串
例P144:StringBuffer buffer=new StringBuffer("安徽城市管理学院");
buffer=buffer.delete(0,2); // 城市管理学院
buffer=buffer.replace(2,4,"职业"); // 城市职业学院
buffer=buffer.reverse(); // 院学业职市城
buffer=buffer.deleteCharAt(1); // 院业职市城
7.3 输入输出流类
7.3.1 数据流概念
1.数据流
数据流是指一组有顺序的、有起点和终点的字节集合,实际上是一个数据序列,它可以看成是数据的导管。输入就是读取数据流,输出则是写入数据流。处理过程:打开流、读取或写入流、关闭流。
Java程序不直接操纵I/O设备,而是在程序和设备之间加入了一个中间介质,这就是数据流,采用数据流的目的就是使程序的输入输出操作独立于具体设备,程序一旦建立了数据流,就可以不用理会起点或终点是何种设备。
Java提供许多数据流的类和方法,封装在java.io包中,编程时用它处理输入输出,只要在程序前面加上语句:import java.io.*: ,即可使用其中的各种I/O方法。
2.输入流与输出流
建立数据流实际上就是建立数据传输通道,将起点和终点连接起来。
输入流可从键盘或文件获得数据,输出流可向显示器屏幕、打印机或文件中传输数据。Java中最基本的流类有2个:基本输入流InputStream,基本输出流OutputStream
3.缓冲流
对数据流的每次操作是以字节为单位进行的,为了提高数据传输效率,通常使用缓冲流(buffered stream),即为一个流配有一个缓冲区(buffer),一个缓冲区就是专门用于传送数据的一块内存。
当向一个缓冲流写入数据时,系统将数据发送到缓冲区,而不是直接发送外部设备,缓冲区自动记录数据,当缓冲区满时,系统将数据全部发送到相应设备。
当从一个缓冲流读取数据时,系统实际是从缓冲区中读取数据。当缓冲区空时,系统将从相应设备自动读取尽可能多的数据充满缓冲区。
7.3.2 Java的标准数据流
标准输入指键盘输入;标准输出指输出到显示器。
标准输入输出功能是通过Java中的系统类System实现的。它在java.lang包中,是一个最终类,有3个公共的静态的成员变量:in , out , err可在程序中直接调用它们。
1.标准输入System.in
System.in作为InputStream类的对象实现标准输入,可以调用它的read方法来读取键盘数据。read方法有3种格式:
public int read( ) // 读入一个字节,作为整数返回
public int read(byte b[]) throws IOException
public int read(byte b[],int off,int len) // 从输入流中读取长度为len的数据,写入字节数组b中从索引off开始绵位置 (不作要求)
如果输入流结束,返回-1。发生I/O错时,会抛出IOException异常。
例:byte a[]=new byte[10]; byte b[]=new byte[10];
System.in.read(a); System.in.read(b,1,2); //若输入abcdef回车abcdef回车
System.out.println((char)a[2]); // c
System.out.println((char)b[0]); // 空
System.out.println((char)b[1]); // a
System.out.println((char)b[2]); // b
System.out.println((char)b[3]); // 空
2.标准输出System.out
格式:void write(int b);
功能:将指定字节b写入输出流,如果b的值大于255,则只输出它的低位字节所表示的值
格式:void write(byte b[]);
功能:把字节数组中的b.length个字节写入输出流
格式:void write(byte b[],int off,int len);
功能:把字节数组b中从索引off开始的len个字节写入输出流
可以调用它的print(不换行输出) , println(换行输出) , 或write方法来输出各种类型的数据。它们不产生输出异常。
write方法用来输出字节数组,在输出时不换行,在输出单个字节时,并不能立即显示出来,必须调用flush方法或close方法强制回显。
例:byte a[]=new byte[15];
System.in.read(a); // 输入abced
System.out.println(a); // 输出[B@480457 乱码
System.out.write(a); // 输出abced
System.out.write(a,1,2); // 输出bc
System.out.println(a[1]); // 98
System.out.write(a[1]); // b
System.out.println(); //强制回显示,也可用System.out.close() ; System.out.flush( )方法;
注:(1)从键盘输入字符串后,保存在缓冲区中的元素还要上两个元素‘\r’(回车键),元素值为ASCII码值。
(2)read方法返回值为int,为实际读入的字节个数。
(3)read会产生输入异常,要么放在try…catch块中执行,要么令mai方法将异常抛出(throws IOException)
long skip(long n) ; (补充)
输入流的当前读取位置向前移动n字节,并返回实际跳过的字节数
例:P48 System.in.skip(2);
7.3.3 java.io包中的数据流类及文件类
java.io包封装了大量的数据流类,支持基于字节流(byte stream)的数据流(这种流对于16位的Unicode码表示的字符流的处理很不方便)和基于字符流(character stream)(以16位Unicode码形式表示)的数据流。
表7.1~7.4 见P148
为了全面管理文件系统,Java还提供了两个文件类:一般文件File和随机文件类RandomAccessFile。前者提供操作系统目录管理的功能,允许用户访问文件属性和路径等。可以顺序访问文件。后者用于对文件以随机操作方式读写数据。
7.3.4 数据流的应用
例:P150 import java.io.* ;
public class SC{
public static void main(String arg[]) throws IOException{
FileReader in=new FileReader("P3.java"); //建立文件输入流,打开P3.java
BufferedReader bin=new BufferedReader(in); //建立缓冲输入流
FileWriter out=new FileWriter("Hello.txt",true);// 建立文件输出流,true表示将数据保存在文件尾部
String str;
while((str=bin.readLine())!=null){ //读入一行
System.out.println(str);
out.write(str+"\n") ; }// 写入"Hello.txt"
in.close();
out.close(); }}
表7.9 字符文件流类的构造 P151
名 称 | 说 明 |
FileReader(String name) | name代表文件名,可包含路径 |
FileReader(File file) | file是文件类对象 |
FileReader(FileDescriptor fdobj) | fdobj代表一个打开的I/O设备 |
FileWriter(File file) | file是文件类对象 |
FileWriter(String name,booleam a) | a取真则将数据添加在文件尾部 |
如果要选择地读写文件,例如读写一行或几行,随机文件RandomAccessFile可实现这种操作,它能从文件的不同位置读写不同长度的数据。
例P151 import java.io.* ;
public class SC{
public static void main(String arg[]) {
String str[]={"First line\n","Second line\n","last line\n"};
try{
RandomAccessFile rf=new RandomAccessFile("hello.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.writeBytes(str[i]);// 字符串转换为字节串添加到文件末尾
rf.seek(0);
System.out.println("\n文件现在内容:");
String s;
while((s=rf.readLine())!=null)
System.out.println(s);
rf.close(); }
catch(FileNotFoundException fnoe){}
catch(IOException ioe){} }}
7.3.5 文件(补充)
1.创建文件
格式:File pathname=new File(args[0])
功能:以路径文件名来建立文件对象
格式:File f=new File(pathname.getPath , fileNames[i])
功能:以路径+文件名创建文件对象
2.File类提供的方法
(1)对文件名操作提供方法
public String getName( ) //得到一个不包含路径的文件名
public String getParent( ) //得到文件上一级的目录名
public File getParenFile( ) //得到文件对象父路径名
public String getPath( ) //返回文件路径名字符串,即路径文件名
public String[] list( ) //返回一个字符串数组,为该文件所在目录下的所有文件名列表,如:String fileName[]=pathName.list( )
public String getCanonicalPath( ) throws IOException //返回该文件对象与系统平台相关的绝对路径,与getAbsoluttPath( )同。
public String renameTo(File newName ) //返回重命名后的文件名
public String getAbsolutePath( ) //返回文件绝对路径名
(2)测试文件属性操作提供方法
public boolean isDirectory( ) //测定是否是目录,如果File代表一个目录,则返回true,否则返回false
public boolean isFile( ) //测定是否是文件
public boolean isAbsolute( ) //测定是否是绝对文件
public boolean exists( ) //测定文件是否存在
public boolean canRead( ) //测定是否是可读文件
public boolean canWrite( ) //测定是否是可写文件
(2)测试文件属性操作提供方法
public boolean delete( ) // 删除当前文件并释放资源
public void deleteOnExit( ) // 执行完后,删除文件
public long length( ) // 返回文件字节长度
public long lastModified( ) //返回文件最后修改时间
(4)为目录操作提供的方法
public boolean mkdir( ) //创建目录
public boolean mkdir( ) //创建包含父目录的目录
public String[] list( ) // 返回当前目录下的文件
public String[] list(FilenameFilter filter) // 返回当前目录下经过滤后的文件
public static File[] listRoots( ) // 返回根目录结构
(5)其他方法
public int hashCode( ) // 返回文件名的哈希码
public boolean setLastModified(long time) //设置文件最后修改时间
public boolean setReadOnly( ) //设置文件只读属性
例:功能:显示指定目录下的子目录,如执行java SC c:\
import java.io.* ;
public class SC{
public static void main(String args[]) {
if(args.length==0) args=new String[]{".."} ;//命令行缺省值
try {
File pathName=new File(args[0]); //取命令行参数
String fileNames[]=pathName.list(); //取pathName下所有文件名列表
for (int i=0;i<fileNames.length;i++)
{ File f=new File(pathName.getPath(),fileNames[i]);//创建路径和文件名创建文件对象f
if(f.isDirectory()) //判断是否是目录
{System.out.println(f.getCanonicalPath()); //输出绝对路径
main(new String[] {f.getPath()}) ; //取下一级子目录
}}}
catch(IOException e)
{ e.printStackTrace( ); }}}
7.4 其他常用类
数学函数类Math,提供了基本数学运算;日期类Date,Calendar和DateFormat,提供了日期和时间操作;随机数类Random提供了随机数生成器;向量类Vector提供了类似于可变长数组的操作。
7.4.1 数学函数类Math
Math是一个最终类,可直接在程序中加Math前缀调用,其成员变量和常用成员方法如下:
static double E // 数学常量e
static double PI // 圆周率Л
static double sin(double a) // 正弦函数,参数为弧度
static double cos(double a) // 余弦函数,参数为弧度
static double tan(double a) // 正切函数,参数为弧度
static double toDegrees(double angrad) // 弧度转换为角度
static double toRadians(double angdeg) // 角度转换为弧度
static double exp(double a) // 常数e的a次幂
static double log(double a) // 自然对数
static double sqrt(double a) // 平方根
static double pow(double a,double b) // a的b次方
static double round(double a) // 四舍五入
static double round(float a) // 四舍五入
static double random( ) // 产生大于等于0.0小于1.0的随机数
static double abs(double a) // 绝对值,参数可以是float,int,long
static double max(double a,double b) //最大值,参数可以是float,int,long
static double min(double a,double b) //最小值,参数可以是float,int,long
例:System.out.println(Math.PI); // 3.141592653589793
System.out.println(Math.sqrt(9)); // 3.0
System.out.println(Math.random()); //0.061703095869295566
System.out.println(Math.round(7.5)); // 8
System.out.println(Math.round(7.4)); // 7
System.out.println(Math.max(9,4)); // 9 Math.max(9,4,10)则错
7.4.2 日期类Math
Java提供了3个日期类:
Date :用于创建日期对象并获得日期
Calendar :可获取和设置日期
DateFormat:用于创建日期格式化器,由格式化器将日期转换为各种日期格式串输出
Date和Calendar类在java.util包中,DateFormat类在java.text包中
Java语言规定的基准日期为1970.1.1 00:00:00格林威治(GMT)标准时
例P154 import java.text.*;
import java.util.*;
import java.awt.* ;
import java.applet.*;
public class SC 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);
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(2001,2,15,9,9,9);
today=now.getTime();
g.drawString("调整后时间"+today.toString(),20,100); }}
7.4.3 随机数类Random
为了使用Java程序有良好的可移植性,应尽可能使用Random类来生成随机数,而不用Math.random( )。
Random有两个构造方法:Random( )(使用系统时间为种子数),Random(long seed)。构造方法只是创建了随机数生成器,必须调用生成器的方法才能产生随机数。Random具有nextBoolean,nextInt等方法。
Random包含在java.util包中。
例:Random r=new Random( );
int i1=r.nextInt( );
int i2=r.nextInt(20); // 产生大于等于0小于20的随机整数
double d1=r.nextDouble( ); //产生大于等于0.0小于1.0的随机数
double d1=r.nextDouble(20.0); // 错
7.4.4 向量类Vector
Vector被设计成一个能不断增长的序列,用来保存对象引用。类似于可变长数组,但功能更加强大,任何类型的对象都可以放入Vector。
Vector包含在java.util包中,常用方法如下。
Vector(int initCapacity,int increment) //构造方法,指定初始容量和增量
void addElement(Object obj) //在尾部添加元素,元素个数自动增1
boolean removeElement(Object obj) //删除第一个与obj相同的元素
void setElementAt(Object obj , int index) // 替换指定位置的元素
Object elementAt(int index) //返回指定位置的元素
int indexOf(Object obj) //返回指定元素obj在向量中的位置
int size( ) //返回元素个数
int capacity( ) //返回向量长度
void trimToSize( ) //按当前元素个数缩减向量长度
Enumeration elements( ) //生成一个向量元素的枚举
例:P157
7.4.5 Class类与Runtime类
通过Class类与Runtime类的方法可以获得运行时的信息,如当前类名、超类名、包名、内存空间以及操作系统名称等
例:P159
第8章 图形用户界面
8.1 组件
组件(Component)是构成GUI的基本要素,通过对不同事件的响应来完成和用户的交互或组件之间的交互。
AWT是Java语言提供的用户界面设计工具,AWT的基本思想是将一个窗口看做一系列嵌套的构件。最外层可以是窗口、菜单条、按钮或包容器等,而包容器又可以包含其他的构件或包容器。
java.awt包提供了基本的java程序的GUI设计工具。主要包括下述三个概念,每个概念对应着一个类:
- 构件——Component,它是该包的核心。是一个抽象类,其他构件都是从它衍生出来的。
- 容器——Container,由Component类衍生而来,用来管理构件。
- 布局管理器——LayoutManager,确定容器内构件的布局。
AWT的界面由组件组成,所有组件都是通过继承Component组件类实现。组件主要有两种:
(1)基本组件:Button(按钮)、Lable(标签)、TextArea(文本区)、TextField(文本框)、List(列表)、Canvas(作图区)、Ssrollbar(滑动条)、Checkbox(复选框)、Choice(选择框)、Menu(菜单)、Mnebar(菜单条)。
(2)容器组件:窗口组件Window,Dialog,Applet,Frame,Panel。容器组件可以容纳AWT组件,也可以包含在AWT容器中。容器最高父类为Container类。
AWT类库的基本层次结构:
Component |
Button | Canvas | Checkbox | CheckboxGroup | Choice | Container | Label | List | Scrollbar | Textcomponent |
panel | window | TextArea | TextField |
Applet | Frame | Dialog |
8.1.1 标签
1.创建标签(Label)
标签的功能是显示单行的字符串。
2.标签Label的构造方法:
(1)Label( ):建立一个新的Label
(2)Label(String text):以text建立一个新的Label
(3)Label(String text,int alignment):以text和指定的布局建立一个新的Label
alignment有3种,分别用Label类的3个常量LEFT(0)(默认),CENTER(1)和RIGHT(2)来表示左对齐、居中对齐和右对齐。
例:Label la1=new Label();
Label la2=new Label("计算机");//按文本区域大小显示
Label la3=new Label("网络",Label.RIGHT);//与("网络",2)等价
add(la1);
add(la2);
add(la3);
add(new Label("技术",Label.CENTER));
3.标签的常用方法:
(1)public int getAlignment( )返回当前的对齐方式
(2)public String getText( )返回当前显示的字符串
(3)public void setAlignment(int alignment)设置对齐方式
(4)public void setText(String label)设置显示的字符串
例:la1.setText(la2.getText()); //将标签la1显示成la2的内容
la1.setAlignment(2); //设置标签la1的对齐方式
add(la1);
8.1.2 按钮(Button)
1.创建按钮
2.按钮的构造方法
(1)Button( ):创建一个没有标题的按钮
(2)Button(String label):创建一个有显示标题的按钮
例:import java.awt.*;
import java.applet.Applet;
public class SC extends Applet{
public void init()
{Button b1=new Button();
Button b2=new Button("确定");
add(b1);add(b2); } }
3.按钮的常用方法
(1)public String getLabel( ):返回按钮的显示标题
(2)public void setLabel(String label):设置按钮上的显示标题
例:String s=b2.getLabel(); //获得b2按钮的标题“确定”
b1.setLabel(s); // 将b1按钮的标题改为s 值“确定”
add(b1);
8.1.3 选项框(Choice)(下拉列表框)
1.创建选项框
每次只能选择其中的一项。
2.选项框的常用方法
(1)public void addItem(String item):向选项框中加入选项item
(2)public int countItems( ):返回选项框中的选项个数(此方法已不用)
改为:getItemCount( ):
(3)public String getItem(int index):返回指定下标值的某个选项
(4)public int getSelectedIndex( ):返回被选中的选项的下标值
(5)public String getSelectedItem( ):返回被选中的选项
(6)public void select(int pos):选择指定下标值的选项
(7)public void select(String str):选择指定的选项
(8)Choice( ):构造一下拉选项框
(9)public void add(String item):向选项框中加入选项item,同(1)
(10)public void insert(String item,int index):在指定位置插入选项
(11)public void remove(int index):删除指定位置选项
(12)public void remove(String item):删除指定字符串
(13)public void removeAll( ):删除所有选项
(14)public Object[] getSelectedObject( ):返回当前选中项的Object数组
例:import java.awt.*;
import java.applet.Applet;
public class SC extends Applet{
String []description={"red","blue","yellow","orange","green","black"};
Label L1=new Label(); //标签对象L1
Label L2=new Label();
Choice c=new Choice(); //下拉列表对象c
public void init(){
for(int i=0;i<6;i++)
c.addItem(description[i]); //将description数组内容作为选项加入
L1.setText(c.getItem(2)); //将标签显示成“yellow”
c.addItem("红色"); //在最后加入"红色"选项,同c.add("红色");
String s=Integer.toString(c.getItemCount()); //获得下拉列表选项数 7个
L2.setText(s); //标签L2显示s值
c.insert("兰",1); //在1的位置插入"兰"选项,"blue"等往后退
c.select(3); //将第3选项"yellow"设为当前选项
c.remove(4); //将第4选项"orange"删除
add(L1); add(L2); add(c); } }
例:import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class SC extends Applet implements ItemListener{
String description[]={"red", "blue", "yellow", "orange", "pink", "grey", "green", "black", "brown"};
TextArea t=new TextArea(10,30);
Choice c=new Choice(); //下拉列表对象c
public void init()
{ t.setEditable(false); //设置文本区域为不可编辑,用户不可输入内容
for(int i=0;i<9;i++)
c.addItem(description[i]); //将description数组内容作为选项加入
add(t); add(c);
c.addItemListener(this);}
public void itemStateChanged(ItemEvent e)
{t.append("\n"+"index: "+ c.getSelectedIndex()+ "\n"+c.getSelectedItem()+ "is selected");}}
//将所选择的序号和内容显示在文本区域中
8.1.4 复选框(Checkbox)和选项按钮(CheckboxGroup)
1.创建复选框
复选框构造方法:
Checkbox( ):创建一个无显示内容的复选框
Checkbox(String label):创建一个指定显示内容的复选框
CheckboxGroup( ):创建一个选项组
Checkbox(String label,CheckboxGroup cbGroup,boolean state):
创建一个指定显示内容字符串,属于选项按钮组cbGroup且状态为state的选项按钮
复选框和选项按钮常用方法:
public void setLabel(String label):设置复选框或选项按钮的标签为label
public void setState(boolean state):设置复选框或选项按钮的状态
public boolean getState( ):获得复选框或选项按钮的状态
public String getLabel( ):获得复选框或选项按钮的标签
例:import java.awt.*;
import java.awt.event.*;
public class SC{
public static void main(String args[]){
Frame f=new Frame("CheckBox");
f.setLayout(new GridLayout(2,1));
Panel p1=new Panel();
p1.setLayout(new GridLayout(1,3));
Checkbox c1=new Checkbox("小肥牛"); //新建C1复选框,标签是"小肥牛"
Checkbox c2=new Checkbox("小肥羊");
Checkbox c3=new Checkbox("蜀王");
p1.add(c1); p1.add(c2); p1.add(c3);
Choice c=new Choice(); //新建下拉列表对象c
c.add(c1.getLabel()); //将c1复选框的标签加入到c的下拉列表框中
c.add(c2.getLabel());
c.add(c3.getLabel());
p1.add(c);
c1.setLabel("金满楼"); //将c1的标签改为“金满楼”
c2.setState(true); //设置c2的状态为选中
f.add(p1); f.pack(); f.show();
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0); } }); } }
运行结果:
2.选项按钮
选项按钮构造方法: CheckboxGroup( )
常用方法:
public CheckboxGroup getCheckboxGroup( ):返回选项按钮所属的复选框组
public void setCheckboxGroup(CheckboxGroup g ):设置选项按钮所属的复选框组
注:要生成选项按钮,必须先生成一个类CheckboxGroup的对象:
CheckboxGroup c=new CheckboxGroup( );
然后再使用下面语句:
Checkbox c1=new Checkbox(“Label”,c,false);
第一参数是选项按钮的标签,第二个是按钮组对象,第三个是状态。
例:import java.awt.*;
import java.applet.*;
public class SC extends Applet{
CheckboxGroup cbg=new CheckboxGroup();
public void init(){
add(new Checkbox("第一",cbg,true));
add(new Checkbox("第二",cbg,false));
add(new Checkbox("第三",cbg,false)); }}
8.1.5 列表框(List)
构造方法:
List( ) :新建一个空的列表框
List(int i ,boolean b) :新建一个指定行数i的列表框,b为true表示可以多选,false则只能单选;
常用成员方法:
public int getItemCount( ) :返回列表内的项目数//现改为getItemCount()
public String getItem(int index):返回下标为index指定的列表项
public synchronized void add(String item):增加一项item
public synchronized void addItem(String item):同上
public synchronized void removeAll( ):清空列表
public synchronized void remove(int index):删除指定下标项
public synchronized void remove(String item):删除指定选项
public synchronized int getSelectedIndex( ):获取选定项的下标
public synchronized int[] getSelectedIndexs( ):获取多个选定项的下标
public synchronized String getSelectedItem( ): 获取选定项内容
public synchronized String[] getSelectedItems( ): 获取多个选定项内容
public synchronized void select(int index ): 选定指定下标的项
public synchronized void deselect(int index ): 取消对指定下标项的选择
public synchronized boolean isIndexSelected(int index ): 判断指定下标项是否被选择
public boolean isMultipleMode( ): 判断列表是否支持多行选择
public void setMultipleMode(boolean bl ): 设置列表是否支持多行选择
例:
8.1.6 单行文本框(TextField)
文本框的构造方法
(1)TextField( ):创建一个默认长度的文本框
(2)TextField( int columns):创建一个列数是columns的文本框(即宽度)
(3)TextField(String text ):创建一个带有初始文本内容的文本框
(4)TextField(String text,int columns ):创建一个带有初始文本内容并具有指定列数的文本框
文本框的常用方法
(1)public void setEchoChar(char c):设定用户输入字符的回显字符
(2)public void setText(String t) :设定文本框的文本内容
(3)public String getText( ) :返回文本框中的文本内容
(4)public void setEditable(boolean b) :设定文本框是否只读属性,false为只读
(5)public int getColumns( ) :返回文本框的列数
(6)public void setColumns( ) :设置文本框的列数
例:
import java.awt.*;
import java.applet.Applet;
public class SC extends Applet{
public void init(){
TextField t1,t2,t3,t4,t5;
Label L1=new Label();
t1=new TextField();
t2=new TextField(5); //宽度为5个汉字
t3=new TextField("网络");
t4=new TextField("计算机",2); //只显示出“计算”
add(t1);add(t2);add(t3);add(t4); add(l1);
L1.setText(t4.getText()); //L1获得t4的内容
t1.setEchoChar('*'); //设置掩码为“*”
t2.setText("Java!"); // 将t2内容改为“Java!!!”
t3.setEditable(false); }} // 将t3设为只读
8.1.7 文本区(TextArea)
文本区的构造方法
(1)TextArea( ):创建一个默认大小的文本区
(2)TextArea(int rows,int columns):创建一个指定行和列数的文本区
(3)TextArea(String text):创建一个带有初始文本内容的文本区
(4)TextArea(String text,int rows,int columns):创建一个带有初始文本内容并具有指定行和列数的文本区
(5)TextArea(String text,int rows,int columns,int scrollbars):在(4)的基础上添加滚动条,scrollbars取值:1(SCROLLBARS_VERTICAL_ONLY)(仅有垂直),2(SCROLLBARS_HORIZONTAL_ONLY)(仅有水平),3(SCROLLBARS_NONE)(无滚动条),4(SCROLLBARS_BOTH)(水平、垂直均有)(除1,2,3数字以外均都有水平垂直滚动条)
文本区的常用方法
(1)public void append(Sting str):在文本区尾部添加文本
(2)public void insert(String str,int pos):在文本区指定位置插入文本
(3)public void setText(String t):设定文本区内容
(4)public int getRows( ):返回文本区的行数
(5)public void setRows(int rows):设定文本区的行数
(6)public int getColumns( ):返回文本区的列数
(7)public void setColumns(int Columns):设定文本区的列数
(8)public void setEditable(boolean b):设定文本区是否只读属性
(9)public void replaceRange(String str,int start,int end):从start到end的文本替换为str的内容
例:import java.awt.*;
import java.applet.Applet;
public class SC extends Applet{
public void init(){
TextArea a1,a2,a3,a4;
a1=new TextArea(5,10); // 5行10列空白文本区
a2=new TextArea("城市管理",8,10);
a3=new TextArea("城市管理",5,10,3);
a4=new TextArea("安徽省合肥人",5,10);
a2.append("\n网络专业"); //a2后追加“网络专业”(\n换行)
a3.setEditable(false); // 将a3设为只读
a3.insert("园林",2); //在第2个字符插入“园林”
a4.replaceRange("安庆",2,4); //将a4文本区中第2~4的字符改为“安庆”
add(a1);add(a2);add(a3);add(a4); } }
8.2 组件布局管理
布局:就是容器中组件的摆放方式,常用的布局管理器有:
1.FlowLayout(顺序)(默认):
将组件依次摆放,每个组件若不设置其大小都将被压缩到最小尺寸。
2.BorderLayout(边界布局):
将组件按north,south,west,east,center五个位置来摆放。
3.CardLayout(卡片布局):
前后依次排列,每次只显示一个卡片。
4.GridLayout(网格布局):
将显示区域划分为若干行列,每个组件占一格。
8.2.1 顺序布局(FlowLayout)
构造函数:
FlowLayout( ):建立一个新的FlowLayout布局,默认居中对齐,组件间有5个单位的水平和垂直间距。
FlowLayout(int align ):按align建立一个新的FlowLayout布局,默认居中对齐,组件间有5个单位的水平和垂直间距。
FlowLayout(int align,int h,int v):按align建立一个新的FlowLayout布局,齐,组件间有h水平和v垂直间距。
FlowLayout共有5种排列方式CENTER(中)、LEFT(左)、RIGHT(右)、LEADING(头)、TAILING(尾)。
8.2.2 边界布局(BorderLayout)
构造函数:
BorderLayout( ):建立一个组件间没有间距的BorderLayout
BorderLayout(int h,int v):建立一个组件间有间距的BorderLayout,h为水平间距,v为垂直间距。
例p171:import java.awt.*;
import java.applet.Applet;
public class SC extends Applet{
Button bn,bs,be,bw,bc;
public void init(){
setLayout(new BorderLayout(5,10)); //设置为边界布局,间距为5,10
bn=new Button("北");
bs=new Button("南");
be=new Button("东");
bw=new Button("西");
bc=new Button("中");
add("North",bn);
add("South",bs);
add("East",be);
add("West",bw);
add("Center",bc); } }
8.2.3 卡片布局(CardLayout)
构造函数:
CardLayout( ):
建立组件间没有水平与垂直间距的、新的CardLayout。
CardLayout( ):建立组件间没有水平间距为h、垂直间距为v的、新的CardLayout。
例P171:import java.awt.*;
import java.applet.Applet;
public class SC extends Applet{
public void init(){
CardLayout card =new CardLayout();
setLayout(card);
setFont(new Font("Arial",Font.PLAIN,24));
for (int i=1;i<=5;i++){
add(String.valueOf(i),new Button("卡片号为:"+i)); }
card.show(this,String.valueOf(2)); } }
8.2.4 网格布局(GridLayout)
构造函数:
GridLayout( ):建立一个新的默认是1行1列的GridLayout
GridLayout(int r,int c):建立一个r行c列的GridLayout
GridLayout(int r,int c,int h,int v):建立一个r行c列的水平间距是h,垂直间距是v的GridLayout
例P172:import java.awt.*;
import java.applet.Applet;
public class SC extends Applet{
Button b1,b2,b3,b4,b5,b6;
public void init(){
setLayout(new GridLayout(3,3)); // 设置3行3列共9个网格
b1=new Button("按钮1");
b2=new Button("按钮2");
b3=new Button("按钮3");
b4=new Button("按钮4");
b5=new Button("按钮5");
b6=new Button("按钮6");
add(new Label("label1"));
add(b1);add(b2);add(b3);
add(new Label1()); // 加一个空标签
add(b4);add(b5);add(b6);
add(new Label("label2")); } }
网袋布局(GridBagLayout)(补充)
网袋布局管理器中引入了一个辅助类GirdBagConstraints类,它可以指定构件的3个信息:
(1)构件单元在容器中的大小和位置,其高度和宽度可能占几个行和列。
(2)单元中构件的大小和位置
(3)容器缩放时,单元发生的变化。
设置构件的大小、位置信息,要按如下步骤进行:
(1)创建一个GridBagConstraints类的对象(如果没有的话)
(2)按照此构件的大小、位置信息设置此对象的各实例变量的值。
(3)调用GridBagLayout的setConstraints方法设置此构件的大小和位置信息,GridBagConstraint对象可以一次创建、多次使用。
构造函数
GridBagLayout():建立一个新的GridBagLayout
GridBagConstraints():建立一个新的GridBagConstraints对象
GridBagConstraints(int gridx,int gridy,int gridwidth,int gridheight,double weightx,double weighty,int anchor,int fill,Insets insets,int ipadx,int ipady):建立一指定参数的GridBagConstraints对象。其中:
- gridwidth和gridheight:用来设置组件所占的单位长度和高度,默认为1。
- Weightx和weighty:用来设置当窗口变大时,组件跟着变大的比例,默认为0,最大为1。数字越大表示组件变大的比例越大
- anchor:当两个组件大不不同时,相对于大组件来说小的放在什么位置,一共有9个值:CENTER(默认)、NORTH、NORTHEAST、EAST、SOUTHEAST、SOUTH、SOUTHWEST、WEST、NORTHWEST。
- Fill:当组件所处的位置有剩余空间时,此参数设置为将组件填满的方向,一共有4个值:NONE(默认)、VERTICAL、HORIZONTAL、BOTH。
- insets:设置组件间彼此的间距,有4个参数分别表示组件上、左、下、右4个方向的间距,默认为(0,0,0,0)
- ipadx和ipady:设置组件边框离组件中心的距离,也就是组件的大小,默认为0。
8.2.5 面板(Panel)的使用
面板是一个无边框的容器,可以包容其他组件或另一个面板。面板目的是为了分层次、分区域管理各种组件。面板实际上是一个必须放在大容器(Applet或Frame)中的小容器。
例P173:import java.awt.*;
import java.applet.Applet;
public class SC extends Applet{
public void init(){
setLayout(new BorderLayout());
setForeground(Color.black); //设置前景色
setFont(new Font("Arial",Font.PLAIN,20)); //设置字体,风格,字号
add("North",new Label("我在Applet中",Label.CENTER));
Panel panel1=new Panel();
add("West",panel1); //在西边加入panel1对象
panel1.setBackground(Color.blue); //设置panel1的背景色
panel1.setForeground(Color.red);
panel1.setLayout(new BorderLayout()); //在panel1中设置新布局
panel1.add("East",new Button("东"));
panel1.add("West",new Button("西"));
panel1.add("Center",new Label("我在Panel1中"));
Panel panel2=new Panel();
add("East",panel2); 在总布局的东边加入panel2对象
panel2.setBackground(Color.green);
panel2.setLayout(new BorderLayout());
panel2.add("North",new Label("我在Panel2中"));
panel2.add("South",new Button("我在Panel2中")); }}
当容器中的组件较多时,用一个布局管理器来管理容器的所有组件就有局限,但一个容器又只能有一个布局管理器,可以通过叠加多个透明容器(如Panel)来实现。
面板和组件的常用方法:
- Panel( ):用默认布局方式创建一个面板
- Panel(LayoutManager layout):用指定布局方式创建一个面板
- public Component add(Component comp):为容器添加一个组件
- public Component add(Component comp,int index):将组件添加到队列的指定位置
- public void add(Component comp,Object constraints):按照限制条件添加组件
- public void remove(Component comp):去除指定组件
- public void setFont(font f):设定组件的字体
- public void setSize(Dimension d):设定组件的宽和高
- public void setVisible(boolean b):设定组件是否可见
- public void setLocation(int x,int y):以设定组件的位置
- public void setBackground(Color c):设定组件的背景色
- public void setForeground(Color c):设定组件的前景色
- public void setBounds(int x,int y,int widty,int height):设定组件的位置和大小
- public void setName(String name):设定组件的名称
- public String getName():返回组件的名称
- public int getX():返回组件的X坐标
- public int getY():返回组件的Y坐标
- public int getHeight():返回组件的高
- public int getWidth():返回组件的宽
- public void paint(Graphics g):画出容器
- public void update(Graphics g):用背景色清除组件,设定画笔为前景色,调用paint方法重画组件。
- Public void repaint():立即调用组件的update方法
8.2.6 手工布局
Java允许使用手工布局放置各个组件,这种方法比较灵活,但用户必须使用setLocation()、setSize()、setBounds()等方法为组件设置大小和在容器中的位置,且使得策略模式的优点将被全部忽略,容器能应付调整大小的事件,代码的可重用性也大大降低,还会导致程序的系统相关。
首先:setLayout(null);语句关闭默认的布局管理器
例P175:import java.awt.*;
import java.applet.Applet;
public class SC extends Applet{
Choice c=new Choice();
Button b1=new Button("Button1");
Button b2=new Button("Button2");
Button b3=new Button("Button3");
public void init(){
setLayout(null);
c.addItem("Item1");
c.addItem("Item2");
c.addItem("Item3");
add(c);
c.setBounds(80,80,100,20);
add(b1);
b1.setBounds(20,20,50,30);
add(b2);
b2.setBounds(100,20,50,30);
add(b3);
b3.setBounds(200,60,50,50); }}
8.3 事件处理方法
8.3.1 事件与事件处理方法
Java通过委托型事件处理机制解决如何对事件作出响应的问题
8.3.2 Java的事件处理机制
能产生事件的组件叫做事件源(如按钮),可给事件源注册一个事件监听器,当事件源发生事件时,事件监听器就代替事件源对发生的事件进行处理,这就是所谓的委托事件处理机制。
注意:事件监听器不一定是包容事件源的容器对象,只要一个对象实现了事件监听器接口就能成为事件监听器。这样处理可使程序中的事件处理代码与GUI代码分离,有利于优化程序结构。
在程序中编写“事件处理”程序段时,通常可以分为以下几个步骤:
(1)确定事件类型
(2)为部件增加一个该事件的监测器:通常名为XXXListener。这些接口包含在java.awt.event和javax.swing.event包中
(3)增加事件处理程序
总体来说,Java事件处理有3部分主要内容:
事件对象:表示事件的内容
事件源:哪个控件上发生了事件
Listener:事件发生了谁来处理
表8.1 Java事件类、对应接口及接口中的方法 P177
ActionEvent一些常用方法:
(1)public String getActionCommand( ):返回事件源的标签
(2)public Object getSource( ):返回产生事件的对象名
(3)public int getModifiers( ):返回事件发生时功能控制键的状态,它们可能是功能键常数:SHIFT_MASK、CTRL_MASK、ALT_MASK
表8.1 Java事件类、对应接口及接口中的方法
事件类/接口名称 | 接口的方法及产生事件的用户操作 |
ActionEvent单击事件类 ActionListener单击事件接口 | actionPerformed(ActionEvent e) 单击按钮、文本行中单击鼠标、双击列表框选项 |
ComponentEvent组件事件类 ComponentListener接口 | componentMoved(ComponentEvent e)移动组件时 componentHidden(ComponentEvent e)隐藏组件时 componentResized(ComponentEvent e)改变组件大小时 componentShown(ComponentEvent e)显示组件时 |
ContainerEvent容器事件类 ContainerListener接口 | componentAdded(ContainerEvent e)添加组件时 componentRemoved(ContainerEvent e)添加组件时 |
FocusEvent焦点事件类 FocusListener接口 | focusGained(FocusEvent e)获得焦点时 focusLost(FocusEvent e)失去焦点时 |
ItemEvent选择事件类 ItemListener接口 | itemStateChanged(ItemEvent e)选择复选框、选项框、单击列表框、选中带复选框的菜单项 |
KeyEvent键盘击键事件类 KeyListener接口 | keyPressed(KeyEvent e)按下键盘时 keyReleased(KeyEvent e)释放键盘时 |
MouseEvent鼠标事件类 MouseListener鼠标按钮事件接口 | mouseClicked(MouseEvent e)单击鼠标时 mouseEntered(MouseEvent e)鼠标进入时 mouseExited(MouseEvent e)鼠标离开时 mousePressed(MouseEvent e)按下鼠标时 mouseReleased(MouseEvent e)放开鼠标时 |
MouseEvent鼠标事件类 MouseMotionListener接口 | mouseDragged(MouseEvent e)拖拽鼠标时 mouseMoved(MouseEvent e)鼠标移动时 |
TextEvent文本事件类 TextListener接口 | textValueChanged(TextEvent e) 文本行、文本区中修改内容时 |
WindowEvent窗口事件类 WindowListener接口 | windowsOpened(WindowEvent e)打开窗口时 windowsClosed(WindowEvent e)关闭窗口后 windowsClosing(WindowEvent e)关闭窗口时 windowsActivated(WindowEvent e)激活窗口时 windowsDeactivated(WindowEvent e)窗口失去焦点时 windowsIconified(WindowEvent e)窗口缩小为图标时 windowsDeiconified(WindowEvent e)窗口复原时 |
例P179:import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class SC extends Applet implements ItemListener{
TextArea area=new TextArea(6,30);
String City[]={"北京","上海","天津","南京","武汉"};
Checkbox cb[]=new Checkbox[5];
Checkbox radio[]=new Checkbox[5];
public void init(){
add(new Label("这是一个选项事件例子"));
add(area);
add(new Label(" 请选择中国的大城市:"));
for (int i=0;i<5;i++){
cb[i]=new Checkbox(City[i]);
add(cb[i]);
cb[i].addItemListener(this); }
CheckboxGroup cbGroup=new CheckboxGroup();
add(new Label("请选择中国最大的城市:"));
for (int i=0;i<5;i++){
radio[i]=new Checkbox(City[i],cbGroup,false);
add(radio[i]);
radio[i].addItemListener(this); } }
public void itemStateChanged(ItemEvent e){
area.append("你选择的是"+e.getItem()+"\n"); } }// e.getItem()选项标签
8.3.4 事件适配器类与类的包容
在java.awt.event包中还声明了一组带Adapter标记的类,称为适配器类,它们是一些抽象类,其中声明的方法与相应的接口的方法完全相同,也是空方法,但在使用它们继承创建新类时,可以不实现所有的方法,只要实现需要的方法即可。
例如:class EnclosingClass{
……
static class NestedClass{……}
class InnerClass{……}
}
被包容的类可以无条件地使用包容它的类的所有成员,包括私有成员,被包容的类的作用域仅限于包容它的类
和类的其他成员一样,被包容的类可以被声明为静态类,非静态被包容类称为内部类(inner class),也可以声明为抽象类或最终类,这些和一般类声明是完全相同的。
例P185:import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class SC extends Applet{
int x1,y1,x2,y2;
public void init( )
{ addMouseListener(new m1());
addMouseMotionListener(new m2()); }
public void paint(Graphics g){
g.drawLine(x1,y1,x2,y2); }
class m1 extends MouseAdapter{
public void mousePressed(MouseEvent e){
x1=e.getX();
y1=e.getY(); }}
class m2 extends MouseMotionAdapter{
public void mouseDragged(MouseEvent e){
x2=e.getX();
y2=e.getY();
repaint(); } } }
作业:P186-6
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class SC extends Applet implements ItemListener {
Label la1=new Label("喜欢的城市:");
Label la2=new Label("喜欢的活动:");
Choice c=new Choice();
List l=new List();
public void init( )
{
setLayout(null);
c.add("北京");
c.add("上海");
c.add("武汉");
c.add("南京");
c.addItemListener(this);
l.add("听音乐");
l.add("看电视");
l.add("看电影");
l.add("看小说");
l.add("打球");
l.addItemListener(this);
add(c); c.setBounds(20,20,100,30);
add(l); l.setBounds(20,50,100,60);
add(la1);la1.setBounds(150,20,100,30);
add(la2);la2.setBounds(150,50,100,30);
}
public void itemStateChanged(ItemEvent e)
{if (e.getSource()==c)
la1.setText("喜欢的城市:"+e.getItem());
else
la2.setText("喜欢的活动:"+l.getSelectedItem());
}
}
第9章 窗口、菜单和对话框
9.1 窗口
9.1.1 创建可关闭窗口
窗口所对应的类为java.awt.Frame,它是java.awt.Window的子类,其常用方法:
方 法 | 功 能 | 返回 类型 |
Frame( ) | 创建一个初始不可见的窗口 | void |
Frame(String title ) | 创建一个指定标题的初始不可见的窗口 | void |
setMenuBar(MenuBar mb) | 设置菜单栏 | void |
remove(MenuComponent mc) | 移除菜单栏 | void |
setVisible(boolean b) | 设置是否可见 | void |
setTitle(String title) | 设置标题 | void |
setSize(int length,int width) | void |
例:import java.awt.*;
import java.awt.event.*;
class Frame1 extends Frame{
public Frame1(){
//窗口构造函数,此例没有调用父类构造函数而是直接在子类中设置窗口属性
Label l=new Label("HI"); //定义窗口中的标签
this.add(l); //在窗口中显示标签
this.setSize(new Dimension(400,300)); //设置窗口大小
this.setTitle("My sceond Frame"); //设置窗口标题 }}
public class SC{
boolean packFrame=false;
public SC(){
Frame1 frame=new Frame1();
frame.setVisible(true); }
public static void main(String args[])
{new SC();} }
9.1.2 窗口事件适配器
例P188
9.1.3 匿名类
例P189
9.1.4 在窗口中加入组件
例P190 import java.awt.*;
import java.awt.event.*;
public class SC extends Frame implements ActionListener{
Button btn1,btn2;
TextField f;
SC( ){
super("Window4"); //调用父类构造函数创建标题为Window4窗口
addWindowListener(new WindowAdapter(){
public void windowsClosing(WindowEvent e){
System.exit(0); }});
setSize(350,200);
btn1=new Button("显示");
btn2=new Button("退出");
f=new TextField(20);
setLayout(new FlowLayout());
add(f);
add(btn1);
add(btn2);
btn1.addActionListener(this);
btn2.addActionListener(this);
show();// 改为setVisible(true);效果一样
}
public static void main(String args[]){
new SC(); }
public void actionPerformed(ActionEvent e){
f.setText("你按下了“"+e.getActionCommand()+"”按钮");
if (e.getSource()==btn2){
for (int i=0;i<1000000000;i++);
System.exit(0);
}}}
注:show或setVisible方法必须位于添加组件语句之后,否则组件显示不出来
9.1.5 多重窗口
例P192
9.2 菜单
菜单与其他组件有所不同,无法直接将菜单添加到容器的某一位置,也无法使用布局管理器对其加以控制,菜单只能被添加到“菜单容器”中
1.菜单条(MenuBar)
是一个水平菜单,它只能被添加到Frame对象中,作为整个菜单树的根基(容器),直接在由java.applet.Applet生成的小应用程序中不能加入菜单,必须先创建窗口。
说明:Swing中的菜单类全部是从Jcomponent类继承而来的,因此可以在任何Jcontainer(包括JApplet)中放置菜单的JmenuBar,而Applet中是不能直接加入菜单的。
Frame fr=new Frame(“菜单条示例”) ;
MenuBar mb=new MenuBar( );
fr.setMenuBar(mb);
fr.setSize(150,100);
fr.setVisible(true);
说明:菜单条(MenuBar)不支持Listener。因为在其中所发生的各种事件,将会自动由菜单项处理。
2.菜单(Menu)
Menu类提供了标准下拉菜单,它可以被添加到菜单条中或其他菜单中
Frame fr=new Frame(“菜单条示例”) ;
MenuBar mb=new MenuBar( );
fr.setMenuBar(mb);
Menu m1=new Menu(“File”);
Menu m2=new Menu(“Edit”);
Menu m3=new Menu(“Help”);
mb.add(m1); mb.add(m2);
mb.setHelpMenu(m3);//在界面上设置帮助菜单
fr.setSize(150,100);
fr.setVisible(true);
3.菜单项(MenuItem)
菜单项是菜单树的“文本叶子”
Menu m1=new Menu(“File”);
MenuItem mi1=new MenuItem(“Save”); //创建“Save”的菜单项
MenuItem mi2=new MenuItem(“Load”);
MenuItem mi3=new MenuItem(“Quit”);
m1.add(mi1); m1.add(mi2);
m1.addSeparator( ); // 添加一条分隔线
m1.add(mi3);
4.复选框菜单项(CheckboxMenuItem)
Menu m1=new Menu(“File”);
MenuItem mi1=new MenuItem(“Save”);
CheckboxMenuItem mi2=new CheckboxMenuItem (“Load”);
//带复选框的菜单项
m1.add(mi1); m1.add(mi2);
CheckboxMenuItem可以通过ItemListener接口进行监听,当复选框状态发生变化后,itemStateChanged()方法将被调用
5.弹出式菜单项(PopupMenu)
弹出式菜单可以在任一组件上弹邮,同时也可以在弹出式菜单中添加菜单项和菜单。弹出式菜单必须被添加到某一“父”组件上
Frame fr=new Frame("PopupMenu");
Button b=new Button("Press Me");
fr.add(b);
PopupMenu p=new PoupMenu("Popup");
MenuItem s=new MenuItem("Save");
MenuItem l=new MenuItem("Load");
fr.add(p);
b.addActionListener(this);
p.add(s); p.add(l);}
如果想要显示弹出式菜单,则需要调用show()方法,如本例使用一个按钮作为触发装置,点击按钮就弹出该PopuMenu
public void actionPerformend(ActionEvent e){
p.show(b,10,10);}
菜单总结:
第一步:定义菜单栏MenuBar类的对象:
MenuBar 对象名=new MenuBar( );
第二步:定义菜单Menu类的对象:
Menu 对象名=new Menu(“菜单名”);
第三步:定义菜单项MenuIttem类的对象:
MenuItem 对象名=new MenuItem(“菜单项名”);
或定义选项子菜单CheckboxMenuItem类的对象:
CheckboxMenuItem 对象名=new CheckboxMenuItem(“选项名”);
第四步:在Frame中加入菜单栏:
Freme类对象名.setMenuBar(“MenuBar类对象名”);
第五步:在MenuBar中加入菜单:
MenuBar类对象名.add(“Menu类对象名”);
第六步:在Menu类的对象中加入菜单项:
Menu类对象名.add(“MenuItem类对象名”);
或Menu类对象名.add(“CheckboxMenuItem类对象名”);
MenuBar类的常用成员方法:
public void MenuBar( ):构造一个菜单栏
public Menu add(Menu m):将指定的菜单加入菜单栏
public void remove(int index):删除指定位置上的菜单
public void remove(MenuComonent):删除指定的菜单
Menu类的常用成员方法:
public void Menu():构造一个菜单
public void Menu(String label):以指定标签构造一个菜单
public MenuItem add(MenuItem mi):增加一个菜单项
public void add(String label):与add(new MenuItem(label))等价
public void remove(int index):删除指定位置上的菜单项
public void remove(MenuComponent mc):删除指定的菜单项
public void removeAll():删除所有的菜单项
public void insert(MenuItem mi,int index):在指定位置处插入一菜单项
public void insert(String label,int index):在指定位置处插入一菜单项
public void insertSeparator(int index):在指定位置处插入一分隔符
MenuItem类的常用成员方法:
public void MenuItem( ):构造一个菜单项
public void MenuItem(String label):以指定标签构造一个菜单项
public void MenuItem(String label,MenuShortcut s):以指定标签和快捷键构造一个菜单项
public void setLabel(String Label):设置菜单项标签
public void setShortcut(MenuShortcut s):设置快捷键
setActionCommand(String command):设置由菜单项引发的动作事件的命令字符串,命令字符串的默认值为菜单项的标签
getActionCommnad():取得事件源的命令字符串
deleteShorcut():删除与该菜单项相关的快捷键
setEnabled(boolean b):设置菜单项是否可选
例:
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class SC extends Applet{
MyFrame f=new MyFrame("My first Frame");
Button b1=new Button("Open");
Button b2=new Button("Close");
MenuBar mb1=new MenuBar();
Menu fi=new Menu("File");
MenuItem file[]={new MenuItem("Open",new MenuShortcut(KeyEvent.VK_O)),
//ctrl+S
new MenuItem("Save",new MenuShortcut(KeyEvent.VK_S)),
//设置快捷方法Ctrl+S
new MenuItem("Exit",new MenuShortcut(KeyEvent.VK_E))};
//Ctrl+E
public void init(){
add(b1);
add(b2);
f.setMenuBar(mb1);
mb1.add(fi);
for (int i=0;i<file.length;i++)
{fi.add(file[i]);}
b1.addActionListener(new b1L());
b2.addActionListener(new b2L());
f.setSize(200,300);}
class b1L implements ActionListener{
public void actionPerformed(ActionEvent e){
f.setVisible(true);}}
class b2L implements ActionListener{
public void actionPerformed(ActionEvent e){
f.setVisible(false);}}
class MyFrame extends Frame{
Label L1=new Label("My Applet Frame");
MyFrame(String s){
super(s);
add(L1); }}}
9.3 对话框
9.3.1 自定义对话框
Dialog构造方法:
Dialog(Frame owner):在指定Frame中构造一无标题的、无模式的对话框
Dialog(Frame owner,boolean model):在指定Frame中构造一无标题的对话框,当model为true时有模式(必须先处理对话框),model为false时无模式
Dialog(Frame owner,String title,boolean model):标题为title,其他同上
Dialog(Dialog owner):在指定Dialog中构造一无标题的、无模式的对话框
Dialog(Dialog owner,boolean model):
Dialog(Dialog owner,String title,boolean model):
常用成员方法:
public void setTitle(String title):设置标题
public void show():显示对话框
public void hide():隐藏对话框
public void setVisible(boolean b):b为true显示对话框,为false不显示
例:import java.awt.*;
import java.awt.event.*;
class SC{
public static void main(String abc[]){
Frame f=new Frame("HI") ;
f.setSize(300,200);
f.show();
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e)
{System.exit(0);} //可关闭窗口
});
Dialog d=new Dialog(f,"HI",false);
d.setSize(100,150);
d.show(); }}
9.4 Swing简介
Swing和AWT的最大差别在于Swing组件类不带本地代码,因此不受操作系统平台的限制,具有比AWT组件更强的功能。
- Swing按钮类和标签类除了显示文本标题外还可以显示图像标题
- 可以为Swing容器加上边框
- Swing组件能自动适应操作系统的外观,而AWT组件总是保持相同外观
- Swing组件不一定非得是矩形的,可以把按钮设计成圆形
- 可以调用Swing组件的方法心迹其外观和行为
- 增加了一个丰富的高层构件集合,如表格(JTable)、树(JTree)
缺点:慢
特点:
- 类的属性被命名为xxx,则相应的的方法命名为:getXxx()、setXxx()、isXxx()
- Swing使用同AWT相同的事件模型。处理Swing中的事件时除了使用java.awt.event包外,还要用到javax.swing.event包
- 大多数情况下在老的AWT组件前加一个“J”即为Swing组件
Swing组件的分类
- 顶层容器:包括JFrame、JApplet、JDialog、Jwindow
- 普通容器:包括JPanel、JScrollPane、JtablePane
- 特殊容器:包括JLayeredPane、JRootPane、JtoolBar
- 基本控件:JButton、JCombox、JList、JMune、JTextFiled等
- 不可编辑信息组件:如JLabel、JprogresserBar
- 可编辑信息组件:如JTextFiled、JTree、JFileChooer、JTable
9.4.1 Swing按钮与标签
1.按钮(JButton)
构造方法:
Jbutton():构造一个没有标签和图标的按钮
Jbutton(Icon icon):构造一个带有图标的按钮
Jbutton(Sting text):构造一个带有标签的按钮
Jbutton(Sting text,Icon icon):构造一个带有标签和图标的按钮
主要成员方法:
public boolean isDefaultButton():返回这个按钮是否为RootPane的默认按钮
setIcon(Icon icon):设置按钮图标
setDisableIcon(Icon icon):设置按钮不激活时显示图标
setRolloverIcon(Icon icon):设置鼠标移到按钮上的图标
setPressedIcon(Icon icon):设置鼠标按下的图标
2.标签(JLabel)
构造方法:
JLabel(Icon icon):构造一个带图片的标签
JLabel(Icon icon,int horizontalAlignment):构造一个带图片且水平对齐的标签
JLabel(String text):构造一个带文本的标签
JLabel(String text,int horizontalAlignment):构造一个带文本且水平对齐的标签
JLabel(String text, Icon icon ,int horizontalAlignment):构造一个带文本图片且水平对齐的标签
主要成员方法:
getIcon():获取JLabel显示的图像对象
setIcon(Icon icon):设置需要显示的图像
getText():返回Jlabel标签显示的字符串
setText(String text):设置需要显示的字符串
getHorizontalAlignment():返回沿X轴的标签内容的对齐方式
setHorizontalAlignment():设置沿X轴的标签内容的对齐方式
getVerticalAlignment():返回沿Y轴的标签内容的对齐方式
setVerticalAlignment():设置沿Y轴的标签内容的对齐方式
9.4.2 Swing工具栏(JToolBar)
作为一个容器来包容任何组件,它支持拖运
构造方法:
JToolBar():构造一个工具栏
JToolBar(int orientation):构造一个指定方向的工具栏
主要成员方法:
addSeparator():在JToolBar的末尾增加一个分割符
addSeparator(Dimension size):在JtoolBar的末尾增加一个指定宽度分割符
getComponentAtIndex(int i):返回指定索引的组件
getComponentAtIndex(Component c):返回指定组件的索引
getOrientation():返回工具栏的方向
setOrientation(int o):设置工具栏的方向
remove(Component comp):从工具栏中删除组件
setBorderPainted(boolean b):设置边界是否可被画
第10章 多线程机制
10.1 多线程的概念
10.1.1 程序、进程和多任务
程序:是对数据描述与操作的代码的集合,是应用程序执行的脚本
进程:是程序的一次执行过程,程序是静态的,进程是动态的。系统运行一个程序就是一个进程从创建、运行到消亡的过程。
多任务:一个系统中可以同时运行多个程序。一个CPU同时只能执行一个程序的一条指令,多任务运行的并发机制使这些任务交替运行。
10.1.2 线程
线程也称为轻型进程(LWP),是比进程更小的运行单位,一个进程可以被划分成多个线程。当一个程序执行多线程时,可以运行两个或多个由同一个程序启动的任务。这样一个程序可以使得多个活动任务同时发生。
10.1.3 多线程
与进程不同的是,同类多线程共享一块内存空间和一组系统资源,所以系统创建多线程开销相对较小。
10.1.4 线程的生命同期与Java的多线程机制
1.线程的生命同期与状态
线程有创建(New)、可运行(Runnable)、运行中(Running)、挂起(Not Runnable)、死亡(Dead)5种状态。
2.Java的多线程机制
java.lang中的线程类Thread封装了所有需要的线程操作控制,有很多方法用来控制一个线程的运行、休眠、挂起或停止。
10.2 创建线程
建立一个线程需要完成三件事:
- 建立一个虚拟的CPU
- 给出线程的执行代码
- 提供代码所操作的数据
两种方法可以创建线程:一种方法是通过继承线程类Thread来创建线程类;另一种方法是建立一个实现Runnable接口的类一创建线程 。
10.2.1 通过继承Thread类创建线程
继承Thread类这种方法中,需要覆盖run( )方法来提供线程的执行代码,定义Thread类的成员变量来提供线程的数据。线程执行时,从它的run( )方法中开始执行,run()方法是线程执行的起点
例:public class SC extends Thread{
int count=1,number;
SC(int num){
number=num;
System.out.println("创建线程"+number); }
public void run(){
while(true){
System.out.println("线程"+number+":计数"+count);
if(++count==3) return; } }
public static void main(String args[]){
for (int i=0;i<3;i++)
new SC(i+1).start(); } }
运行结果:创建线程1
创建线程2
创建线程3
线程1:计数1
线程1:计数2
线程2:计数1
线程2:计数2
线程3:计数1
线程3:计数2
例:P208
public class SC extends Thread{
public static void main(String args[]){
testThread t1=new testThread("线程1");//仅是一空线程对象,没有启动这一线程,系统不为它分配资源,
testThread t2=new testThread("线程2");
t1.start(); t2.start(); } } //启动线程
class testThread extends Thread{
public testThread(String str)
{super(str);} //调用父类构造方法为线程对象命名
public void run(){
for (int i=0;i<3;i++){
System.out.println(getName()+"在运行"); //getName返回线程名称
try
{sleep(1000); //用休眠1000毫秒来区分哪个线程在运行
System.out.println(getName()+"在休眠");}
catch(InterruptedException e){} }
System.out.println(getName()+"已结束"); }}
说明:由继承Thread创建的子类,必须覆盖run方法,因为run方法是abstact抽象方法
10.2.2 通过Runnable接口创建线程
如果是Applet类应不能再继承Thread类(不能多继承),这时可以通过接口Runnable直接创建线程对象。接口中只声明了一个未实现的run方法。
线程体的构造方法:
public Thread([ThreadGroup group][,Runnable target][,String name])
其中group指明该线程所属的线程组,target是执行线程体的目标对象,它必须实现接口Runnable,name则为线程名。这三个参数均可任意没有。
任何实现接口Runnable的对象都可以作为一个线程的目标对象,类Thread本身也实现了接口Runnable,因此我们可以通过两种方法实现线程体。
(1)定义一个线程类,它继承类Thread并重写其中的方法run(),这时在初始化这个类的实例时,目标对象target可为null
(2)提供一个实现接口Runnable类作为线程的目标对象,在初始化一个Thread类或者Thread子类的对象时,把目标对象传递给这个线程实例,由该目标对象提供线程体run()。这时实现接口Runnable的类仍然要以继承其他父类。
例:P210
import java.awt.*;
import java.applet.Applet;
import java.util.*;
import java.text.DateFormat;
public class SC extends Applet implements Runnable{
Thread clockThread=null;
public void init(){
setBackground(Color.blue);
setForeground(Color.yellow); }
public void start(){
if(clockThread==null){
clockThread=new Thread(this,"Clock2");
//Thread(ThreadGroup group,String name)name是线程名,group指定线程所属的组
clockThread.start(); } }
public void run(){
Thread myThread=Thread.currentThread();
//找到当前执行的线程,返回它的引用
while(clockThread==myThread){
repaint();
try{ Thread.sleep(1000);
} catch(InterruptedException e){}
} }
public void paint(Graphics g){
Date date=new Date();
DateFormat formatter=DateFormat.getTimeInstance();
String str=formatter.format(date);
g.drawString(str,5,10); }
public void stop()
{clockThread=null;} }
10.2.3 可运行状态(Runnable)
Thread MyThread=new Thread()
MyThread.start();
这样该线程处于可运行(Runnable)状态,注意,这状态并不是运行中状态(Running),因为线程也许实际并未真正运行(因很多计算机是单CPU)。当一个线程正在运行时,它是可运行的,并也是当前正运行的线程
10.2.4 不可运行状态(Not Runnable)
当下面四种情况发生时,线程就是进入不可运行状态:
(1)调用了sleep()方法
(2)调用了suspend()方法
(3)为等候一个条件变量,线程调用wait()方法
(4)输入输出流中发生线程阻塞
我们来看看下面这个例子:
Thread myThread=new Thread();
MyThread.start();
try{ myThread.sleep(10000);}
catch(InterrupedException e){
}
对于上面四种情况,都有特定的返回可运行状态的方法与之对应,对应方法如下:
(1)如果线程处于睡眠状态中,sleep()方法中的参数为休息时间,当时间过去后,线程即为可运行的。
(2)如果一线程被挂起,须由其他线程调用resume()方法来恢复该线程的执行。
(3)如果线程在等待条件变量,那么要停止等待的话,要该条件变量所在的对象调用notify(),notifyAll()方法。
(4)如果在I/O流中发生线程阻塞,则特定的I/O指令将结束这种不可运行状态
10.2.5 死亡状态(Dead)
一般可通过两种方法实现:自然撤消或是被停止
1.自然撤消
public void run(){
int i=0;
while(i<100){
i++;
System.out.println(“i=”+i); }}
当run()方法结束后,该线程应自然撤消了
2.被停止
Thread myThread=new Thread();
MyThread.start();
try{Trhead.currentThread().sleep(10000);
} catch(InterruptedException e)
myThread.stop();
10.2.6 非法状态处理(IllegalThreadStateException)
当一个线程刚被创建后,只能对它调用start()或stop()方法,若调用其他方法则会引起非法状态处理。同样对于任何状态,如果所调用的方法与状态不符,都会引起非法状态处理。
10.3 线程的优先级
Java为使有些线程可以提前得到服务,可给线程设置优先级。在单个CPU上运行多线程时采用了线程队列技术,Java虚拟机支持固定优先级队列,一个线程的执行顺序取决于其对其他Runnable线程的优先级。优先级分1~10同,默认级别是5级。
Thread的公用静态常量表示:
public static final int MAX_PRORITY=10 (最大优先级10)
public static final int MIN_PRORITY=1 (最小优先级10)
public static final int NORM_PRORITY=5 (默认优先级5)
public final int getPriority( ) //获得线程优先级
public final setPriority(int newPriority) //设置线程优先级
10.4 线程的调度与控制
10.4.1 线程类的方法
1.线程的类方法
Thread类的静态方法,即可直接从Thread类调用
CurrentThread( ):返回正在运行的Thread对象名称
sleep(int n):让当前线程休眠n毫秒
2.实例方法P213
10.4.2 控制线程的状态
1.挂起一个线程:suspend( )方法
t.suspend():将t暂停执行,必须由其他线程调用t.resume()恢复,不提倡使用该方法,因为容易造成死锁
2.停止一个线程:stop( )方法
当线程完成运行并结束后,将不能再运行。另不可用t.stop()强行终止线程。注:这并没有消灭这个线程,只是停止线程的执行。但这个线程不能用t.start()重新启动。不提倡采用这种方法,易造成线程的不一致。要通过设置flag通知一个线程应该结束。
3.线程休眠:sleep(long )方法
Thread.sleep()使一个线程暂停运行一段固定时间。
4.连接线程:join( )方法
t.join()使当前的线程等待,直到t结束为止,线程恢复到可运行状态。三种调用格式:
(1)join():如当前线程发出调用t.join(),则当前线程将等待线程t结束后再继续执行。
(2)join(long millis):如当前线程发出调用t.join(long millis),则当前线程将等待线程t结束或最多等待mills毫秒后再继续执行。
(3)join(long millis,int nanos):如当前线程发出调用t.join(long millis,int nanos),则当前线程将等待线程t结束或最多等待mills毫秒+nanos纳秒后再继续执行。
5.暂停(退让)线程:yield( )方法(只让给同优先级运行)
调用t.yield()方法可暂停当前运行线程,但处于可运行状态,让同优先级线程先运行。若没有同等优先级的线程是可运行状态,yield方法将什么也不做。
6.中断线程:interrupt( )方法
如果一个线程t在调用sleep(),join(),wait()方法被阻塞时,则t.interrupt()方法将使t的中断状态被清除,中断t的阻塞状态,并且将接收到InterruptException异常。
一个线程可以通过获取另一个线程的引用,调用该线程的interrupt()方法来中断另一个sleep或wait线程的执行
7.了解线程的状态:isAlive( )方法
返回true则线程处于Runnable或Not Runnable状态(即已启动但还没有运行结束),返回false则说明线程处于New Thread或Dead状态
创建 |
可运行 |
运行中 |
死 亡 |
其他阻塞 |
其他阻塞 |
其他阻塞 |
start() 调度
时间片到yield() run(),stop()结束
时间到 sleep()
interrupt() join() wait()
synchronized()
获得互斥
使用权
notify()
notifyall()
线程状态的转换图
例:public class SC{
public static void main(String args[]) throws Exception{
int i=0;
Hello t=new Hello();
t.start();
while(true){
System.out.println("早上好!"+i++);
if (i==2&&t.isAlive()){
System.out.println("Main waiting for Hello!");
t.join(); //等待t运行结束
}
if (i==4) break; }}}
class Hello extends Thread{
int i;
public void run(){
while (true){
System.out.println("嗨"+i++);
if(i==4) break; } } }
运行结果:
早上好!0
早上好!1
Main waiting for Hello!
嗨0
嗨1
嗨2
嗨3
早上好!2
早上好!3
10.5 线程的同步机制与共享资源(自学)
第11章 图形与多媒体处理
AWT(Abstract Windows Toolkit)是抽象窗口工具包的缩写,其支持窗口界面的创建、简单图形的绘制、图形化文本输出和事件监听。Java所有与图形有关的功能都包含在AWT包里。
11.1 基本图形
绘制基本图形要使用AWT中的Graphics类
11.1.1 直线
格式:public void drawLine(int x1,int y1,int x2,int y2)
例:import java.awt.Graphics;
public class Line extends java.applet.Applet{
public void paint(Graphics g){
g.drawLine(50,50,100,100);} }
11.1.2 矩形
public void drawRect(int x,int y,int width,int height)
public void fillRect(int x,int y,int width,int height)//与drawRect相比,画出矩形框后用前景色填充。
public void drawRoundRect(int x,int y,int width,int height,int arcWidth,int arcHeight)//最后两个参数代表圆角
public void fillRoundRect(int x,int y,int width,int height,int arcWidth,int arcHeight)//用前景色填充内部
public void draw3DRect(int x,int y,int width,int height,boolean raised)//raised为true时为三维矩形凸起, 为false时为三维矩形凹下
public void fill3DRect(int x,int y,int width,int height,boolean raised)
11.1.3 椭圆
public void drawOval(int x,int y,int width,int height) //x,y是包围椭圆的矩形左上角位置,width,height是椭圆的宽度和高度。
public void fillOval(int x,int y,int width,int height) //用前景色填充内部
如:public void paint(Graphics g)
{g.drawOval(30,20,60,60); //画圆
g.fillOval(130,20,80,50);}
11.1.4 圆弧
public void drawArc(int x,int y,int width,int height,int starAngle,int arcAngle)
//starAngle起始角(以角度为单位),确定了圆弧的位置,arcAngle张角确定了圆弧的大小,取正(负)值为沿逆(顺)时针方向画出圆弧。当张角大于360时,画出的就是椭圆。
public void fillArc(int x,int y,int width,int height,int starAngle,int arcAngle)
11.1.5 多边形
public void drawPolygon(int xPoints[],int yPoints[],int nPoints)//xPoints[]是一整数数组,用以存放多边形坐标点X坐标值,yPoints[]参数存放对应Y坐标值,nPoints则表示 共有几个坐标点。
public void fillPolygon(int xPoints[],int yPoints[],int nPoints)/
例:import java.awt.*;
public class SC extends java.applet.Applet{
int x[]={30,60,115,72,67};
int y[]={40,30,15,52,100};
int m=x.length;
public void paint(Graphics g)
{g.drawPolygon(x,y,m);} //m-1则少一边,m+1则出错
}
11.1.6 复制与清除图形
copyArea(int x,int y,int width,int height,int dx,int dy)//前四能参定义要被复制的屏幕的矩形区域,最后2个参数则表示新区域与原始屏幕区域的偏移距离。
clearRect(int x,int y,int width,int height)//清除指定矩形区域
要清除整个applet区域,可先调用Applet类的size()方法得到整个applet的宽度和高度。如:g.clearRect(0,0,size().width,size().height)
例:import java.awt.*;
public class SC extends java.applet.Applet{
public void paint(Graphics g){
g.fillRoundRect(120,20,80,60,30,40);
g.copyArea(120,20,80,60,50,100);
g.clearRect(120,20,80,60);}}
11.2 画布
11.2.1 画布的作用
画布(Canvas)是用来绘图的组件,基作用和Windows的画图板类似。Canvas继承自Component类,有自己的paint方法,能响应鼠标和键盘事件。
11.2.2 创建画布的实例
例P228
11.3 文字输出
11.3.1 字符串、字符和字节输出
(1)字符串输出方法:public void drawSting(String str ,int x,int y)
(2)字符输出方法:drawChars(char chars[],int offset,int len,int x,int y)
(3)字节输出方法:drawBytes(byte bytes[],int offset,int len,int x,int y)
11.3.2 字体控制
通过类Graphics或组件的方法getFont()和setFont()可以获取或设置当前使用的字体。
字体构造方法:Font(String name,int style,int size)
name:字体名,如:“宋体”、“楷体”、“Times New Roman”、“Courier”
style:字体风格,如:Font.BOLD(粗体)、Font.ITALIC(斜体)、Font.PLAIN(普通),由于它们被定义为整数常量,可以进行相加运算生成复合style,如:
Font fn=new Font(“TimesRoman”, Font.BOLD+Font.ITALIC,28)
size:字体大小
我们可通过getToolkit().getFontList()来得到系统的AWT工具集所支持的字体列表。如:
Toolkit systk=Toolkit.getDefaultToolkit( );
String fonts=systk.getFontList( );
创建了Font对象以后,就可以利用Graphics类中提供的drawString(),drawChars()等方法来显示字符串与字符:
首先用setFont()方法,将创建的Font对象设为当前所用字体,再用drawString(),drawChars()输出字符。
格式:public void setFont(Font font); //设置当前字体信息
public void drawString(String str,int x,int y)//在指定位置输出字符串
public void drawChars(char data[],int offset,int len,int x,int y)//在指定位置输出字符数组,offset表示从第几个字符位置开始,len表示共显示几个字符。
public font getFont()//获取当前所用的Font对象
11.4 颜色控制
java在Color类中实现对颜色的控制,可改变前景色和背景色。Java将常用颜色定义为颜色常量,如表11.1 P231,用法如:Color.blue
构造方法:
Color(float r,float g,float b)//red,green,blue三原色浮点值,取值在0.0~1.0间
Color(int r,int g,int b)//red,green,blue三原色整数值,取值在0~255间
Color(int rgb)//指定一个整数代表三原色混合值,取值0~7代表蓝色,取值8~15代表绿色,取值16~23代表红色,(此方法有问题,不要用)
11.4.1 为不同对象设置颜色
setColor(Color c)//设置当前所用前景色
getColor() //获得当前所用前景色
Java还提供了设置整个Applet的前景和背景的方法:
setForeground(Color c)
setBackground(Color c)
getForeground(Color c)
getBackground(Color c)
例:import java.awt.*;
public class SC extends java.applet.Applet{
char c[]={'计','算','机','专','业'};
Font f1=new Font("隶书",Font.ITALIC,16);
Font f2=new Font("楷体",Font.ITALIC,16);
Color c1=new Color(100,200,150);
public void paint(Graphics g){
g.setFont(f1);
g.setColor(Color.RED);
g.drawString("网络专业",20,30);
g.setColor(c1);
g.setFont(f2);
g.drawChars(c,0,3,20,50);}}
例:import java.awt.*;
public class SC extends java.applet.Applet{
Color c1=new Color(0,0,255);
Color c2=new Color(255,50,100);
Color c3=new Color(0,250,100);
public void paint(Graphics g){
setForeground(c1);
setBackground(c2);
g.drawRect(20,30,50,100);
setForeground(c3); //将影响Applet中所有已经用其他任何颜色所绘制的图形及显示的文本
setBackground(Color.green);//同上,所以在一个程序中不要用两遍引此方法
g.drawRect(20,230,50,100);}}
11.5 图像处理
11.5.1 图像种类
11.5.2 图像的显示
1.载入图像方法
java.applet.Applet和java.awt.Tookit分别提供了getImage方法载入指定的图像
格式1:Image getImage(URL url);
要指明图像文件的绝对URL。
格式2:Image getImage(URL url,String name);
要指明图像文件的基地址以及图像文件名。当Applet与图像文件处于同一目录下时,可用getCodeBase()获取基地址,如果图像与包含Applet的HTML文件在同一目录下,可用getDocumentBase()获得基地址。
对于Application来说,必须通过类Toolkit提供的方法getImage()来载入图像,其方法定义为:
格式1:Image getImage(URL url);
格式2:Image getImage(String filename)
得到Toolkit对象有两种方法:一种是通过类Toolkit的静态方法getDefalutToolkit() 如:
Image img=Toolkit.getDefaultToolkit().getImage(“ImgFile.gif”)
另一种是调用某一组件的实例方法getToolkit() 如在一组件中使用:
Image img=getToolkit().getImage(“ImgFile.gif”)
2.显示图像
(1)boolean drawImage(Image img,int x,int y,ImageObserver observer):img是要显示的图像,x,y指明图像的位置,observer接收有关图像的信息。
(2)boolean drawImage(Image img,int x,int y,Color bgcolor,ImageObserver observer): bgcolor为背景色
(3)boolean drawImage(Image img,int x,int y,int width,int height,ImageObserver observer): width,height指明图像的大小
(4)boolean drawImage(Image img,int x,int y,int width,int height,Corlor bgcolor, ImageObserver observer):
例:import java.applet.*;
import java.net.*; //应要使用URL对象
import java.awt.*;
public class imag extends Applet{
Image image;
public void init() {
String url = "http://www.shu.edu.cn/~xyx/img/shnet.jpg";
try {
image = getImage(new URL(url));
} catch(Exception e){} }
public void paint(Graphics g) {
g.drawImage(image, 0, 0,this); } }
第二种格式完整的程序如下:
import java.applet.*;
import java.net.*;
import java.awt.*;
public class imag2 extends Applet{
Image image;
URL imgur=null;
public void init() {
try { imgur=new URL("http://www.shu.edu.cn/~xyx/img/shnet.jpg"); }
catch (MalformedURLException e) {
System.out.println("Can´t open the URL "); }
image=getImage(imgur); }
public void paint(Graphics g) {
g.drawImage(image, 0, 0,this); } }
11.5.3 图像的缩放显示
img=getImage(getCodeBase(),”W.jpg”)
int w=img.getWidth(this); //返回图像高度
int h=img.getHeight(this); //返回图像宽度
g.drawImage(img,100,50,w/2,h/2,this); //缩小一倍
11.6 动画处理
11.7 加载声音文件
目前Java Applet可以播放声音,Application则不行
格式1:play(URL soundDirectory,String soundfile)
格式2:play(URL soundURL):URL为存放声音文件的URL,soundfile为文件名
使用java.applet.Applet类中所定义的getAudioClip()方法可以载入一个声音文件,方法:格式1:getAudioClip(URL soundDirectory,String soundfile)
格式2:getAudioClip (URL soundURL):
例:AudioClip sound;
sound=getAudioClip(getDocumentBase(),”bar.wav”)
当声音文件被载入后,则可以使用java.applet.AudioClip类中相关方法(play(),loop(),stop())对其进行操作:
sound.play():播放载入的声音文件
sound.loop():循环播放一个载入的声音文件
sound.stop():停止播放的声音文件
1.如何将字串 String 转换成整数 int?
A. 有两个方法:
1). int i = Integer.parseInt([String]); 或
i = Integer.parseInt([String],[int radix]);
2). int i = Integer.valueOf(my_str).intValue();
注: 字串转成 Double, Float, Long 的方法大同小异.
2 如何将整数 int 转换成字串 String ?
A. 有叁种方法:
1.) String s = String.valueOf(i);
2.) String s = Integer.toString(i);
3.) String s = "" + i;
注: Double, Float, Long 转成字串的方法大同小异.
这是一个例子,说的是JAVA中数据数型的转换.供大家学习引
package cn.com.lwkj.erts.register;
import java.sql.Date;
public class TypeChange {
public TypeChange() { }
//change the string type to the int type
public static int stringToInt(String intstr)
{Integer integer;
integer = Integer.valueOf(intstr);
return integer.intValue(); }
//change int type to the string type
public static String intToString(int value)
{Integer integer = new Integer(value);
return integer.toString(); }
//change the string type to the float type
public static float stringToFloat(String floatstr)
{Float floatee;
floatee = Float.valueOf(floatstr);
return floatee.floatValue(); }
//change the float type to the string type
public static String floatToString(float value)
{Float floatee = new Float(value);
return floatee.toString(); }
//change the string type to the sqlDate type
public static java.sql.Date stringToDate(String dateStr)
{return java.sql.Date.valueOf(dateStr); }
//change the sqlDate type to the string type
public static String dateToString(java.sql.Date datee)
{return datee.toString();}
public static void main(String[] args)
{java.sql.Date day ;
day = TypeChange.stringToDate("2003-11-3");
String strday = TypeChange.dateToString(day);
System.out.println(strday);}
}
JAVA中常用数据类型转换函数
虽然都能在JAVA API中找到,整理一下做个备份。
string->byte:Byte static byte parseByte(String s)
byte->string:Byte static String toString(byte b)
char->string:Character static String toString (char c)
string->Short:Short static Short parseShort(String s)
Short->String:Short static String toString(Short s)
String->Integer:Integer static int parseInt(String s)
Integer->String:Integer static String tostring(int i)
String->Long:Long static long parseLong(String s)
Long->String:Long static String toString(Long i)
String->Float:Float static float parseFloat(String s)
Float->String:Float static String toString(float f)
String->Double:Double static double parseDouble(String s)
Double->String:Double static String toString(Double)
邵丽萍 邵光亚 张后扬 编著
清 华 大 学 出 版 社
教
案
授课教师:张 昊
职 称:讲 师
课程设计:
要求:设计Applet程序,单击鼠标左键,在单击处画一小圆,单击右键则画一小方形。
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class SC extends Applet implements MouseListener {
int State=0;
int x=0,y=0;
public void init( )
{ addMouseListener(this);}
public void paint(Graphics g){
if (State==1)
{g.drawOval(x-10,y-10,20,20);}
else if (State==2)
{g.drawRect(x-8,y-8,16,16);}
}
public void mousePressed(MouseEvent e){
x=e.getX();
y=e.getY();
if (e.getModifiers()==MouseEvent.BUTTON1_MASK) //判断单击左键
State=1;
else if (e.getModifiers()==MouseEvent.BUTTON3_MASK) //判断单击右键
State=2;
repaint();
}
public void mouseClicked(MouseEvent e){ }
public void mouseEntered(MouseEvent e){ }
public void mouseExited(MouseEvent e){ }
public void mouseReleased(MouseEvent e){ }
public void update(Graphics g) // 保留上一次画图状态
{if (State==1 || State==2)
paint(g);
else
super.update(g);
}}