Java程序语言设计 课程代码04747
学习方法:先阅读大纲中对应章节的学习目的和学习要求、考核知识点与考核要求。
考核内容:考核各章所规定的基本要求、知识点的知识细目都属于考核内容,重点内容覆盖密度更高。
整体目录结构
[TOC]
一、第一章 Java概述
1. Java语言的简介
1.1 Java是什么?
java是计算机编程语言,java语言的前身是Oak语言,是由美国Sun公司在1991年推出;在1995年Sun公司将其更名为Java;2009Sun公司被Oracle公司收购。
1.2 Java语言的特点
-
语法简单、功能强大、安全性高。
java是一个面向对象的语法,与C不同,去掉了C语言中的指针等复杂概念;(语法简单)
JVM自动回收垃圾,保证程序的可靠性。(功能强大)
java语言要先编译再解释运行,保证了代码的安全性。
-
跨平台性运行。
因为JVM的存在,保证了Java的跨平台运行性。
-
解释编译运行。
-
多线程。
-
丰富的API。
2. Java开发环境的安装
2.1 什么是JDK?
JDK名为Java软件开发工具包,包含了Java的编译、解释、运行的过程所需的所有工具。
2.2 JDK的组成
bin目录下包含了Java的开发工具,如javac编译器,java解释器等。
jre目录下包含了java所需的运行环境——java虚拟机。
lib目录下包含了java开发类库。
javac编译器,java解释器。:star:
2.3 设置环境变量
安装jdk的时候需要设置系统的环境变量,而设置环境变量的意义是什么?
在没有设置环境变量的时候,我们要想使用doc命令启动应用,就必须前往应用的安装目录下,找到应用的启动程序才能启动;而配置了环境变量后,我们可以在任何地方直接使用doc命令来启动应用。
3. Java程序示例
3.1 Java程序的两种形式
java程序分为两种,一种是Java应用程序,另一种是Java小应用程序,又称为java小程序。
java的入口函数为main方法,而main方法执行完毕也代表着整个java程序的结束。
java的源程序的扩展名为.java,编译后的字节码文件扩展名是.class,有JVM载入执行。
3.2 Java程序示例
public class Hello{
public static void main(String[] args) {
System.out.print("Hello World");
}
}
3.3 Java程序编译运行过程
- 由
javac编译器,将源文件(.java)文件编译为.class字节码文件。 - 由
java解释器,将.class字节码文件载入JVM并运行。
3.4 IDE是什么?
IDE是继承开发环境,这是提供给开发人员使用的程序开发环境,包含了编译器、解释器、调试器等工具,常见的开发IDE由Eclipse、IDEA等。
4. Java中的面向对象:star:
4.1 什么是面向对象?
面向对象是一种软件开发的方法,通常包括3个方面:
- 面向对象的分析(OOA)
- 面向对象的设计 (OOD)
- 面向对象的编程(OOP)
面向对象就是将相关的数据和方法(描述和行为),抽象成一个整体,从更高的层次来进行数据的建模,更贴切现实,便于理解,简单易用。
4.2 对象与类的关系
对象是类的一个具体实现,而类是对象的一个抽象模板。
对象具有两个特性——状态和行为;状态描述的是对象的属性,而行为描述的是对象的方法。
4.3 面向对象的三大技术
-
封装
隐藏对象的属性和实现细节,只提供使用的方法,提高了安全性。
-
继承
提高了代码的复用性,继承是多态的前提。
-
多态
父类或接口引用指子类或实现类对象。提高程序的拓展性、灵活性。
使用相同的操作名,能跟根据具体的对象自动选择对应的操作。(可以向上转型或向下转型,以便使用不同的方法)。
二、第二章 数据和表达式
1. 基本元素和语法
1.1 注释和语句
-
注释的三种形式
-
单行注释:
/* */作用:对变量、一行程序进行简短的说明。
-
多行注释:
/* */作用:对方法、设计逻辑、基本思想等进行说明。
-
文章注释:
/** */作用:在类或方法的头部进行声明,表示对方法和类描述说明;如返回值,方法形参进行说明。
-
-
语句、分号和块
-
语句
语句是java程序的最小执行单位,程序之间以";"分号进行分隔。
-
语句块
以"{ ...语句;... }"大括号开始并结尾的整块代码成为语句块。
-
1.2 关键字
关键字是java中内部保留的字符,他们都有着特殊的意义,在使用的时候不能把这些关键字声明为标识符使用。
1.3 标识:star:
标识符的说明
标识符是由字母、数字、下划线、"$"美元符号组成的字符串,其中不能以数字开头;标识符区分大小写,没有长度限制。
标识符的作用:可用作变量名、方法名、接口名和类名等。
Jva源码使用的是Unicode编码。
1.3 编程风格
- 在声明变量名的时候,最好能望名知意,望名知途。
- 类名与接口名每个单词之间首字母大写。
- 变量名、方法名、首个单词首字母小写,其他单词首字母大写。
- 常量名字母全大写。
- 习惯用注释解释用意不明显的代码段。
2. 基本数据类型:star:
2.1 java数据类型的分类
java数据类型分为两种,一种是基本数据类型,第二种是引用数据类型。
注意:数组也是引用数据类型。
-
基本数据类型
基本数据类型 标识符 整数类型 byte、short、int、long 浮点数类型 float、double 字符型 char 布尔类型 boolean -
引用数据类型(复合数据类型)
引用数据类型 标识符 类类型 class 数组 接口类型 interface
2.2 Java整数类型
-
整数类型和字节大小
一个字节由8个二进制位(bit)组成
整数类型 整数长度 字节数 范围 byte 8(位) 1 -128~127 short 16 2 -32768~32767 int 32 4 网上有 long 64 8 网上有 整数类型可以用二进制、八进制、十进制、十六进制来表示,由0和1组成的是二进制;以0开头为八进制;以0x开头的是十六进制。
-
java提供的特殊整型常量值
类型 最大值 最小值 int Integer.MAX_VALUE Integer.MIN_VALUE long Long.MAX_VALUE Long.MIN_VALUE
2.3 转义字符说明
在Java中,有些字符由特定的含义,不能当作普通的标识符类使用,应当使用转移字符——'\'斜杠类转义使用。
3. 表达式
3.1 表达式的含义
表达式是由运算符和操作数组成,对操作数进行运算符指定的操作。
3.2 操作数相关
3.2.1 常量
常量的含义:常量指的是在程序运行过程中,其值不变的量;并且只有基本类型与String类型才有相应的常量。
3.2.2 变量
-
变量的定义
变量指的是在程序运行过程中,其值可以改变的量;并且变量要先声明才能使用。
变量的所属类型既可以是简单数据类型,也可以是引用数据类型。
3.2.3 变量的分类
变量按照声明地方的不同可以分为两类,在类中方法外定义的变量称为成员变量;而在方法內部声明的变量称为局部变量。
3.2.4 变量的作用域
变量的作用域指的是声明的变量能够使用的范围。
成员变量的使用范围为整个类,而方法变量的使用范围为其声明方法的内部。
注意:变量的使用讲究就近原则。
4. 运算符
分算符主要分为以下几类:
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 其他运算符
4.1 算术运算符
算术运算符就是最基本的加、减、乘、除、取余。
而且取模操作还可以用于负数,结果的符号与第一个操作数的符号相同。
4.2 关系运算符
关系型运算符包括大于、小于、等比较操作。关系型运算符都是二元运算符,也就是每个运算符需要带两个操作数。
"==" 与 "!="两种运算符用于任何数据类型。
4.3 逻辑运算符
逻辑运算符包括逻辑与(" && ")与逻辑或("||")和逻辑非("!")。
java对逻辑与和逻辑或提供短路操作功能,在运算时,先计算左侧表达式的值,如果使用该值能够确定整个表达式的值,那么将不再计算右边表达式的值。
4.4 位运算符
4.4.1 位运算符的定义
什么是位运算符?
位运算符就是对两个二进制数,进行逻辑运算。
4.4.2 常见的位运算符
-
取反(~)
如果一个二进制数的位数为0,那么取反结果是1,如果位为1,结果是0。
-
按位与(&)
两个二进制数对应的位数都为1,结果才为1,否则结果为0。
-
按位或(|)
两个二进制数,只要对应的位数有一个为1,那么结果就是1,否则就为0
-
异或(^)
两个二进制数,对应的位数相同则结果为0,不同则结果为1
-
左移(<<)
将二进制数像左边进行移动,最左边的舍弃,最右边的补零。
-
右移(>>)
将二进制想右移动,最右边舍弃,最左边补位。
注意:在右移运算符中,如果操作的二进制数的十进制是为负整数,那么再对其二进制进行右移的时候,左边的补位应该为1,如果是正整数,那么补位为0.
-
无符号右移(>>>)
与右移相同,但是不关注正负整数的问题,左边统一补位为0.
4.4.3 位移运算说明
int a << 1:表示将a的二进制左移一位,得到的结果时a的两倍。
int a >> 1:表示将a的二进制右移一位,得到的结果时a的2/1。
如果左移或右移的位数大于等于32,那么再进行位移之前会先对位移数取余(加入向左或向右位移32位,则取余公式位 32 % 32),所以实际的位移结果位 << 0,表示不位移。
4.5 其他运算符
如+=、-=、*=等扩展赋值运算符,以及? :三元运算符。
5. 进制的转换:star:
5.1 十进制——>二进制
-
十进制为正整数的情况
- 方法一:除二取余,直到被除数为0为止,然后从下往上得到结果。
- 方法二:用 8421法。
- 方法二教学地址:www.bilibili.com/video/BV1Uz…
-
十进制为负整数的情况
步骤:
- 用以上两个方法得到原码。
- 先补位,然后对原码取反(0变1,1变0),得到反码。
- 对反码+1。
5.2 二进制——>十进制
-
二进制0开头表示其原十进制为正整数时
用8421法进行权位*系数 = 结果 的方法。
-
二进制1开头表示其原十进制为负整数时
步骤:
- 先减1。
- 然后取反得到反码。
- 然后使用8421法,权位*系数 = 结果,得到其十进制数。
6. 表达式的提升和转换:star:
java是一种强类型语言,不支持变量类型之间的自动任意转换,有时必须显示的进行变量类型的转换;这种转换叫做强转。
6.1 自动转换的顺序
能够自动类型转换的类型顺序为:
byte->short->char->int->long->float->double
6.2 Java自动转换总结
java的自动转换分为自动类型转换和强制类型转换.
-
自动类型转换
从字节数小类型的转换为字节数大类型的可以自动类型转换。
整型数据与小数之间可以互相转换,但是有可能会出现精度损失的问题。
-
强制类型转换
从字节数大的转换为字节数小的类型,不能自动转换,需要强制类型转换。
第三章 流程控制语句
一、第一节 Java程序的结构
一个Java源文件可以有多个类定义,但是只能有一个类为public公有类。
1. Java包的概念与导入
包是类的容器,在定义包时应该避免包冲突;并且一个包中不能有相同类名的类或接口。
包的引入格式为:package 包路径1.包路径2
注意:如果一个类中有package语句,那么此语句一定是在此Java文件中的第一条非注释语句。
2. 引入语句的使用
在Java源文件中,如果想要使用某个包下的某个类,那么需要使用import语句;将要使用的类进行导入。
import引入语句的使用格式:import 包名1.包名2.类名;
如果要导入包中的所有类,可以使用通配符" * ",格式:import 包名1.包名2.*
二、第二节 流程控制语句
java中以下三种语句分别对应不同的流:
赋值语句 -> 顺序流
分支语句 -> 分支流
循环语句 -> 循环流
1. 赋值语句
1.1 定义
表达式可以当作一个值赋给某一个变量,这样的语句叫做赋值语句。
实例:int x = 10 + 11;
2. 分支语句
2.1 定义
分支语句可以根据一定的条件,来控制程序的执行流向。
2.2 分类
java中的分支语句有两种,一是if语句,二是switch语句。
2.2.1 if语句
if关键字后的必须要跟一个逻辑值表达式,这个表达式一定是能够得到一个boolean值。
if...else...的匹配原则::star:
在java中,else语句优先与离它最近的if语句匹配,但是前提是在同一个语句块中。
2.2.2 switch语句
switch关键字后的表达式与if不同,它必须要求表达式的计算结果是int类型或者字符类型,这样才能与后面的case语句进行匹配。
并且Java规定switch语句表达式不能使用浮点数类型或Long类型的表达式。
3. 循环语句
3.1 Java中的循环语句
在Java中一共分为三种:
- for循环
- while循环
- do...while循环
3.2 for循环
3.2.1 语法格式
for (初始语句; 条件表达式; 迭代语句){
// 循环体
}
3.2.2 for循环的特点
初始语句与迭代语句可以有多个,使用,逗号进行分隔。
3.2.3 for循环的执行顺序
初始化语句 ——> 条件表达式 ——> 循环体 ——> 迭代语句
3.3 while循环
3.3.1 语法格式
while(条件表达式) {
// 循环体
}
3.3.2 特点
while循环与for循环的条件表达式都不能以数值类进行判断,要求表达式最总结果必须是一个布尔类型。
3.4 do...while...循环
3.4.1 语法格式
do{
// 循环体
} while (条件表达式)
3.4.2 特点
do...while语句与while与for循环语句不同,do语句至少会执行一次。
3.4.3 do语句执行顺序
先执行循环体 ——> 然后判断条件表达式是否成立,成立则继续执行,不成立的退出循环,所以do语句的循环体至少会执行一次。
3.5 循环语句的使用选择
一般来说常用的是for循环与while循环,而do语句则很少使用。如果知道具体的循环次数,那么选用for循环语句,反之使用while循环。
4. 跳转语句
java中存在两个关键字,能够配合流程控制语句与循环语句使用——break与continue。
4.1 break
4.1.1 作用语句
-
switch语句
当使用在switch语句中时,表示跳出此次case语句,也就是跳出本次分支流程,继续往后执行。
-
循环语句
当使用在循环语句中时,表示跳出循环,结束循环语句。
-
与标号配置使用在语句块中(不常用)
4.2 continue
continue语句作用在循环语句中,表示跳出本次循环,直接进入下次循环。
三、第三节 简单的输入/输出
1. Scanner类
Scanner类位于java.util包下,是一个用于读取不同类型输入值的类。
1.1 创建Scanner对象
Scanner scanner = new Scanner(System.in);
System.in:代表标准输入流,默认指键盘输入。
1.2 提供的方法
Scanner类提供了nextLine()、nextDouble、nextInt等方法,用于读取不同类型的数据。
四、第四节 异常处理
1. 异常的定义
指的是在程序运行过程中,可能出现非正常情况,可能导致JVM非正常停止所出现的情况。
2. 异常的分类
java把异常分成两类,程序出现非正常情况但是可以修复,这种我们称为异常;反之不可简单修复的称为错误。
在java中,都定义了一些常见的异常类和错误类;异常类的顶级父类是Exception,而错误类的顶级父类是Error;同时他俩的父类又是Throwable。
在java中,总共把异常分为受检异常和运行异常。
2.1 受检异常
受检异常是指程序执行期间发生严重事情的后果,常见的受检异常有ClassNotFoundException,IOException等。
2.2 运行时异常
运行时异常是指程序执行时发生的逻辑错误而引起的异常。常见的运行时异常有索引越界异常,除0异常等。
3. 异常处理
Java中处理异常的方式有两种:
- 使用
try...catch...finally语句捕获异常。 - 使用throw往上(往方法的调用处)抛异常。
注意的是,使用try...catch...finally捕获异常时,finally中的代码都会执行,位移不执行的方法就是在finally语句块执行之前使用了System.exit(0);程序来终止了JVM虚拟机的运行。
第四章 面向对象程序设计
一、第一节 类和对象
1. 类的定义
1.1 Java类的组成
首先类的定义也成为类的声明,而一个类中的组成元素主要为两个——成员变量与成员方法。
1.2 类定义修饰符的权限
1.2.1 权限修饰符的说明
权限修饰符代表了所声明的变量或方法的访问范围;而在Java中,权限修饰符有以下几种(访问范围从大到小排列):
public 、protected、default、private
public:表示公有的意思,访问范围——可以被任何对象访问。
protected:受保护的意思,访问范围——不同包且非父子类关系不能访问。
default:默认的意思,访问范围——只能同包访问,包不同则不能互相访问。
private:私有的,访问范围——只能同类互相访问。
1.3 关于类的定义补充
- 源文件的文件名必须和类名相同。
- 所有类的顶级父类都是
Object。
2.构造方法
2.1 构造方法的定义
构造方式时一个类中的特殊方法,它用于定义此类的对象;每个类中都有一个默认的无参构造。
2.2 构造方法的特点
- 构造方法的名字与类名相同。
- 与普通方法的调用不同,构造方法的调用由
new关键字调用。 - 构造方法支持重载,也就是支持多个构造方法。
- 构造方法不用为
native、final等关键字修饰。 - 构造方法没有返回值。
- 构造方法不能从父类继承。
2.3 什么是方法的重载?
Java中,如果方法名相同,而形参列表不同,这样的多个方法就称为方法的重载。
方法签名:方法名+形参列表。
2.4 构造方法的作用
构造方法的唯一作用就是为了创建类的实例,也就是创建对象。
3.对象
3.1 什么是对象?
简单来说,对象就是类的实例。
3.2 对象和类的关系
类时对象的模板,而对象时类的实例。
举一个简单的例子,手机设计图假如是一个类,那么一台真实的手机则是一个对象。
3.3 对象的声明过程
- 声明变量,在变量声明后,内存中就为其建立了一个引用,但是现在这个引用没有任何指向,也就是说它为null,在内容中没有实际地址。
- 使用new关键字申请内存地址。
- 将变量的引用指向申请的内存地址。
只有对象真正实例化之后,内存中才有内存地址。
3.4 对象的使用
调用成员方法——对象名.成员方法名。
调用成员变量——对象名.成员变量名。
二、第二节 定义方法
1. 什么是按值传送?
在Java中调用方法传递参数的过程,我们称为按值传送。
按值传送的意思也就是按照型参的类型传递;如果参数为基本数据类型,那么传值就会以复制的方式传送;如果参数为引用类型,那么传值就会以传递内存地址值的方法传送。
三、第三节 静态成员
1.静态变量
1.1 什么是静态成员?
采用static修饰的成员变量或成员方法都成为静态成员。
1.2 静态成员的内存加载过程
首选要说明,静态成员的加载优先级是要高于普通成员的。静态成员在类被JVM进行加载的时候就会加载;而普通成员则是要实例化对象的时候,依靠构造方法才会加载。
总结由如下几点:
- 静态成员变量随着类的加载而加载。
- 不同静态成员将共享同一块内存空间(堆内存中的静态池中)。
1.3 定义静态变量的原因
当多个对象需要共享一个变量的时候,就可以定义静态变量来实现。
1.4 静态变量的引用
前面提到了,静态变量是跟随类的加载而加载的,所以调用的时候由类名进行调用。
2.静态方法
2.1 静态方法的使用需要注意点
- 静态方法只能使用其内部定义的参数或静态变量。
- 静态方法不能被重写。
四、第四节 包装类
1. 什么是包装类?
包装类是一种特殊得基本类型。
2.自动装箱和自动拆箱的含义
-
自动装箱
由基本类型转为包装类型的过程称为自动装箱。
-
自动拆箱
由包装类型转为基本类型的过程称为自动拆箱。
注意:自动装箱和拆箱仅能用于基本数据类型与包装类型之间。
1. 方法的定义说明
- 方法名必须是一个合法的标识符。
- 如果没有返回值类型,则使用void关键字说明。
- 修饰符段
- 形参列表
- 方法体
第五章 数组和字符串
一、第一节 数组
1. 声明数组
1.1 数组的定义
- 数组是由相同类型的元素按一定顺序排列而成的集合。
- 在Java中,数组是一个对象;而数组中的元素可以是基本类型也可以是引用类型。
- 数组必须要先声明后使用。
1.2 一维数组的定义格式
类型 数组名[] 或者 类型[] 数组名
2. 创建数组
2.1 声明数组说明
数组的声明仅仅是声明了一个引用,而内存中还未创建其真实地址。所以要想使用数组,不光要声明,还要进行数据的初始化。
2.2 数组的初始化
首先,数组的初始化分为静态初始化、动态初始化两种方法。
静态初始化:
所谓的静态初始化就是在声明数组的时候对数组进行赋值,完成数组初始化的过程。
例如:int[] a = {1, 2, 3};
动态初始化:
而所谓的动态初始化则是使用new关键字,进行数组的声明并创建对象,为其分配内存空间;但是要注意,在使用动态初始化的时候,要指定初始化数组的长度。
然后使用下标的方式为数组的每个索引赋值。
例如:
int[] a = new int[3];
int[0] = 1;
int[1] = 2;
int[2] = 3;
3. 访问数组元素
3.1 访问数组元素的方式
当定义好一个数组之后,要想访问数组中某个索引处的元素就需要以下标的方式从数组中取出对应索引下标上的元素。
如:
int[] a = {1,2,3};
int b = a[1]; // b=2
但是需要注意的是,如果在使用下标获取数组中的元素时,索引下标超出了数组的原本长度,那么则会引发索引越界异常。而一个数组的最大索引为 = 数组的长度 -1。(索引从0开始)
且数组的下标可以是整数类型与表达式类型。
4. 多维数组
4.1 什么是多维数组?
简单来说,就是一个数组中由多个元素,而没有给元素又是一个单独的数组。这样的情况我们就称之为多为数组。
4.2 二维数组的定义格式
- 格式一:
int[][] a; - 格式二:
int a[][]; - 格式三:
int[] a[];
4.3 多维数组的初始化
和一维数组一样,多维数组的初始化也分为静态初始化与动态初始化两种方式。
4.3.1 静态初始化
静态初始化也就是在声明数组的时候进行赋值。
例如:int[][] a = {{1,2}, {2,3}, {3,4}}
4.3.2 动态初始化
当对多维数组进行动态初始化时有两种内存分配方法。
-
直接分配
直接分配指的就是在声明多维数组的时候,直接指定维度的大小。
如:
int[][] a = new int[2][5]; -
按维分配
按维分配指的就是分别为每一个维度分配内存空间大小。
如:
int[][] a = new int[2][]; a[0] = new int[2]; a[1] = new int[2]; a[2] = new int[2];以上分配方式就是动态初始化中的多维分配。
4.4 多为数组的引用
多维数组的引用方式为:数组名[第一位下标][第二位下标]。
二维数组的第一维称为行,第二位称为列。
4.5 二维数组的长度
二维数组也有.length属性,其长度有第一维长度所定义。
列:int[][] a = new int[2][5];,因二维数组的长度由第一维定义,所以a数组的长度为2。
5. 数组的特点
5.1 数组特点总结
- 数组中的元素类型都是相同的。
- 数组的长度是定长的,数组初始化后数组的长度不可改变。
5.2 Arrays提供的方法
Arrays类是关于数组的一个工具类,在这个类中提供了许多关于数组的方法。
-
equals(type[], type[])用于比较两个数组的值是否相同。
-
sort(type[])对数组进行排序。
二、第二节 字符串类型
1. 字符串的定义
字符串是由单个字符组合而成,在java中字符串是一个对象。
2. 字符串的声明
在java中,字符串分为常量与变量两种。
常量格式:Stirng a = "123";
变量格式:String a = new String("123")
在java中,系统会自动为程序中出现的常量字符串创建一个String对象。
3. 字符串的操作
- String类型的对象一旦创建则不可变。
- 凡是对String类型对象的任何拼接操作,都不会影响原字符串本身,而是会生成一个新的字符串对象。
4. String与StringBuffer的区别与使用
-
区别:
String对象一旦创建后不可改变,凡是对String对象改变操作,系统会直接生成一个新的String对象。
而StringBuffer对象则是可以通过
append()方法,在原先的字符串上进行拼接,且系统不会生成一个新的对象。 -
使用:
不变字符串采用String类型,而常变字符串采用StirngBuffer类型。
5. equals()与==的区别
equals()方法比较的是两个字符串的内容是否相等,而==比较的是两个对象的地址值是否相同。
还是就是两个内容相等的常量字符串使用==结果是true,因为在堆内存中存在字符串常量池概念,在声明字符串常量的时候,发现常量池中有相同的字符串,则会进行复用,而不会新生成一个字符串常量。
例如:
String a = "aaaa";
String b = "aaaa";
a == b; // 结果为true
三、第三节 Vector类
1. 什么是Vector类?
-
数组的缺点
在java中数组的缺点在我看来有两个,一是数组中的元素类型全部要统一,二是数组的长度是定长的。
而
Vector类就是为了解决数组的缺点而生,Vector类可以看作是变长数组。
2. Vector类的特点
- Vector类的实例对象的大小可以改变。
- Vector类保存的元素可以完全不一样。
- Vector类只能保存引用类型的对象,不能保存基本类型的对象。
3. Vector类的成员变量
int capacityIncrement:增量的大小(每次增加Vector对象的大小)。int elementCount:Vector类中元素的数量。Object elementData[]:保存元素的数组。
第六章 继承与多态
一、第一节 子类
1. 子类的概念
Java中子类的概念是体现在继承关系中;被继承的类称为父类,继承的类称为子类。
2. 如何定义父子类
将共性内容放入父类,特殊内容由其子类自己实现。
3. extends
extends是实现继承的关键字。
使用格式:public class Son extends Parent{}
4. Object类
Object类是所有java类的间接或直接父类,是最顶级的类。
4.1 Object类的方法
- toString
- equals
- getClass
4.2 equals与==
equals方法与==都是比较引用对象的地址值是否相等,只要两个对象的地址值不同,所得的结果一定是false。
注意:要判断两个对象的成员属性值是否相等,必须要重写Object类的equals()方法,不能使用从Object原始的equals()方法。
5. 单重继承
多重继承说明
多重继承指从多个类派生出一个子类,及一个子类有多个父类。
在java中鄙弃了多重继承,只有单重继承,及一个类只能有一个直接父类;而多重继承的特点由接口实现,也就是一个类能实现多个接口。
这就是java的单继承,多实现。
5.1 继承时的注意
- 构造方法不能继承。
- 子类不能直接访问其父类中的私有成员。
6. 对象转型
6.1 对象转型的定义
父类引用或接口引用指向子类对象,这称为对象的转型。
6.2 多态性的定义
类的变量既可以指向本类对象,也可以指向其子类对象,这为对象的多态性。
6.3 关于对象转型后的使用
前提:父子类中拥有相同的属性成员的情况下。
使用多态的口诀:属性(成员变量)看左边,行为(成员方法)看右边。
6.4 转型的分类
- 向上转型:父类引用指向子类对象。(自动类型转换)
- 向下转型:子类引用,指向父类对象。(需要强转)
二、第二节 方法覆盖与多态
1. 方法覆盖
1.1 重载与重写
- 重载:重载表示两个方法的方法名和返回值相同,但是参数列表的个数、类型、位置不同,这样的两个方法就称为重载。
- 重写:重写的前提时两个类由继承关系的前提,两个类中的方法签名完全相同(即返回值、方法名、参数列表相同),则为方法的重写。
1.2 方法重写时的注意事项
- 方法的签名必须相同。
- 子类方法的访问权限不能高于父类方法访问权限。
- 子类方法抛出的异常不能比父类方法抛出的异常多。
- 如果子类已经重写了父类方法,那么如果想要调用父类中的方法时,需要使用
super关键字进行调用。
1.3 super的使用注意
super.method()调用的方法是一定是直接父类的方法,也有可能是祖先类中的。
2. 调用父类构造方法注意事项
- java要求一个父类对象,必须要在子类对象初始化之前进行初始化。
- 在执行子类的构造方法时,会自动调用父类默认的构造方法。
- 如果要显示的调用父类的构造方法,那么
super()方法必须放在子类构造方法体的第一行。
3. 多态
3.1 Java中多态的体现
- 重载一个方法名可以看作是多态。
- 父子类之间直接或间接重写方法,由对象去调用时,也是多态。
3.2 多态方法的调用
多态的情况下,执行的是对象真正类型(运行时)的相关方法。
三、第三章 终极类和抽象类
1. 终极类
1.1 final关键字的作用
final`是Java中的一个关键字,它表示终极的意思,可以修饰类、成员方法、成员变量。
1.2 final关键字的使用注意事项
- 被
final修饰的类不能被继承。 - 被
final修饰的方法不能被重写。 - 被
final修饰的变量,其值不能改变。
1.2 终极类的定义
被final关键字修饰的类称为终极类。
1.3 终极方法的定义
被final关键字修饰的方法称为终极方法。
格式:
public final int test() {
}
1.4 终极变量
被final修饰的变量称为终极变量,实际上他会成为一个常量,所以其值不能改变。
如果把一个引用类型的变量标记为final终极的,那么这个变量将不能指向其他类型的对象,但是它原本所指的对象的属性值可以改变。
2. 抽象类
2.1 抽象类的定义
被abstract关键字修饰的类称为抽象类。
2.2 抽象类的意义
在程序过程中,有时候需要创建某个类,代表一些基本行为,并且为其规范定义一些方法,但这些方法又不适合在这个类中加以实现,所以就将本类定义为抽象类。具体的时候由其子类根据实际情况去实现这些方法。
2.3 抽象方法
被abstract修饰的方法称为抽象方法。
2.4 抽象类使用注意事项
- 抽象类中可以定义成员属性和默认方法,这些属性和方法可以被子类所调用。
- 抽象类不能实例化,只有抽象类的子类才能实例化。
- 抽象类能够包含常规类中的任何成员方法。
- 抽象类中通常包含抽象方法,抽象方法没有具体实现。
- 抽象类中也可以包含非抽象方法,反之非抽象类中不能包含抽象方法。有抽象方法的类一定是抽象类,而抽象类中不一定有抽象方法。
- 如果一个抽象类中只定义了抽象方法,那么使用接口则更为合适。
2.5 抽象方法的继承
如果一个类继承抽象类,那么必须重写抽象类中的抽象方法。如果不重写抽象方法,那么子类也应该为一个抽象类。
四、第四节 接口
1. 接口的定义
1.1 什么是接口?
在定义类的时候,使用interface代替class关键字所定义出来的类,称为接口。
接口中只能包含抽象方法和final修饰的常量。
1.2 接口的定义格式
public interface Demo() {
}
1.3 接口的定义要求
接口与一般类一样,本身也具有数据成员变量和方法;但是不同于类的是,接口中的成员变量必须初值,且不能改变;而方法也只能是抽象方法。
在接口中定义的成员变量都默认为终极静态变量,系统会自动为其加上final与static俩关键字。
2. 接口的实现
在Java中,一个类可以实现多个接口。
2.1 接口实现注意事项
- 在实现接口的时候,实现类一定要重写接口中的所有方法,否则改实现类就必须定义为一个抽象类,而接口的中的方法就必须定义为抽象方法。
- 实现一个接口的类,也必须实现此接口的父接口。
- 不能使用接口来创建对象,必须使用其实现类才能创建对象。
第七章 输入流和输出流
一、第一节 数据流的基本概念
1. 数据流的介绍
1.1 流的概念
磁盘与其他设备关联的数据源抽象为流。
1.2 数据流的概念
数据流是指一组有顺序、有起点和终点的字节集合。
1.3 数据流的分类
数据流分为输入流和输出流两类。
输入流只能读不能写,而输出流只能写不能读;且输入流必须指定数据源与输入流相连。
1.4 Java中关于数据流所在包和类
java.io包下提供了表示数据流的4个基本抽象类。
-
字节流相关
InputStream与OutputStream -
字符流相关
Reader与Writer
以上四个类都是属于抽象类。
2. 输入数据流
2.1 输入数据流的含义
输入数据流指的是只能读不能写的数据流,用于向计算机内输入信息使用。
2.2 InputStream
InputSteam是所有字节输入流的顶级抽象类,所有的字节输入流都直接或间接继承了InputStream抽象类。
2.3 InputStream主要方法
int read():从输入流中读取一个字节的二进制数据。int read(byte[] b):从输入流中读取一个b数组大小的数据。int read(byte[] b, int off, int len):从输入流中读取长度为len的数据,从byte数组的off下标位置开始放置。int available():返回目前可以从数据流中读取的字节数(但实际读操作得到的字节数可能大于该返回值)。
注意:当输入流读取结束时,使用read()方法返回值的为-1,表示没有数据可以读取了。
3. 输出数据流
3.1 输出数据流的含义
输出数据流指的是只能写不能读的数据流,用于从计算机中写出数据。
3.2 OutputStream
OutputSteam是所有字节输出流的顶级抽象类,所有的字节输出流全都直接或简介继承了OutputStream这个抽象类。
3.3 主要方法
void write(int i):将字节i写到数据流中。void write(byte[] b):将byte数组中的所有字节写入数据流。void write(byte[] b, int off, int len):将数组中从下标off开始的len个长度的字节,写入数据流。void flush():刷新此输出流,并强制写出所有缓冲区的字节。
3.4 输出缓冲区
输出缓冲区的存在就是为了减少IO次数,提交传输效率。
举例说明:
假设我们往一个文件中写入数据,如果每写一次都立刻去进行IO操作,将数据写入文件,那么在写入数据较少的情况下,势必会影响我们的传输效率;而缓冲区的作用正是在这里。
我们预先设定好缓冲区的大小,当我们写入的数据大小没有缓冲区大小大的时候,那么数据会先进入缓冲区,等待下一次数据到来;等两次的数据大小和大于了缓冲区大小时,那么就会执行IO操作,将数据写入文件。
在这种方式下,传输末尾阶段总会有一段数据因为数据量不够而呆在缓冲区中,所有flush()方法的作用就是将这部分数据强制刷出缓冲区,写入文件中。
二、第二节 基本字节数据流类
1. 文件数据流
1.1 文件数据流说明
文件数据流包括FileInputStream(文件输入流)与FileOutputStream(文件输出流),这两个类用来进行文件的IO处理,其数据源或数据终点都是文件。
1.2 文件数据流的使用注意事项
- 当使用
FileInputStream文件输入流时,所指定的文件数据源对象不存在则会产生FileNotFoundException异常。 - 当使用
FileOutputStream文件输出流时,如果指定的输出文件不存在,则会新建;如果输出文件已存在,那么新写入的内容将覆盖原本内容。 - 如果在读写文件,或生成新文件时发生错误,则会产生
IOException异常。
2. 过滤器数据流
过滤器数据流类:FilterInputStream,该类时继承的InputStream抽象类。
过滤器数据流的创建:一个过滤器数据流在创建时与一个已经存在的数据流相连接。
过滤器数据流的作用:在从原数据流读取数据时,过滤器数据流就能够对原始输入数据流内容进行特定处理。
2.1 缓冲区数据流
缓冲区数据流简介
缓冲区数据流分为缓冲区输入流BufferedInputStream与缓冲区输出流BufferedOutputStream;它们是在数据流上增加了以恶缓冲区,都属于过滤器数据流。
这两个缓冲区数据流又继承了过滤器数据流类。
缓冲区输入流:BufferedOInputStream extends FilterInputStream
缓冲区输出流:BufferedOutputStream extends FilterOutputStream
缓冲区的作用
当读写数据时,数据以块为单位先进入缓冲区(块的大小可以自己设置),其后的读写操作则作用域缓冲区。采用这种方法可以提高IO效率。
缓冲区输出流使用注意事项
在关闭缓冲区数据流之前,应该先使用flush()方法,强制刷出剩余数据;以确保缓冲区内的所有数据全部写入输出流。
2.2 数据数据流
数据数据流简介
数据数据流主要分为数据输入流DataInputStream与数据输出流DataOutputStream,它俩也是继承了过滤器数据流。
数据数据流的作用
数据数据流允许通过数据流来读写Java的基本类型。
常用方法介绍
数据输入流
byte readByte()Stirng readUTF()int readInt()- ...
数据输出流
void writeByte(int v)void write(int b)void writeUTF(String str)- ...
2.3 对象流
对象流简介
Java提供了把对象写入数据流,或从数据流中读出的功能;通过java.io包下的ObjectInputStream 对象输入流与ObjectOutputStream 对象输出流两个类实现。
对象输入流的关键方法
从一个流中读取对象的方法:readObject(),把数据流以Object类型返回,然后需转换为合理的对象操作类型。
通过对象流对对象的持久化操作也和对象的序列化分不开。
2.4 序列化
对象的持久性?
能够记录自己的当前状态,以便将来能够复原;这样的能力称为对象的持久性。
什么叫序列化?
把对象转换为字节序列的过程称为对象的序列化;把字节序列恢复为对象的过程称为反序列化。
对象序列化的注意事项
- 序列化只能保存对象的非静态成员变量,不能保存静态变量和任何成员方法;并且只能保存变量的值,而不能保存变量的修饰符。
- 任何使用
transitent关键字标明的成员变量都不会被保存。 - 如果一个可持久化对象中包含了另一个不可持久化元素时,则正式持久化操作失败。
- 如果一个可持久化对象的成员变量引用了另一个不可持久化对象,但是这个变量已有关键字
transient修饰,那么则整个对象可以进行持久化。
三、第三节 基本字符流
1. 字符流
从JDK1.1开始,java.io包下加入了专门处理字符流的类,他们是Reader和Writer派生出来的一系列类。
Reader和Writer是两个抽象类,也是所有字符流的祖类。
2. 字符转换流
2.1 字符转换流分类
字符转换流是用来在字节流和字符流之间做转换使用的。
核心类就是在java.io包下的InputStreamReader 字符输入转换流和OutputStreamWriter字符输出转换流。
2.2 字符转换流的作用
把以字节方式表示的流转换为特定平台上的字符表示。简而言之就是在字节流与字符流之间相互转换。
2.3 构造方法
InputStreamReader(InputStream in):将字节流转化为字符流。OutputStreamWriter(OutputStream out):将字符流转化为字节流。
3. 字符缓区冲流
3.1 关键类
java.io包下的BufferedReader字符缓冲区输入流与BufferedWriter 字符缓冲区输出流。
3.2 作用
作用与字节缓冲区流相同,都是为了提高IO效率,故而加入了缓冲区这一功能。
并且也有flush()刷新方法,在数据传输尾声,需要使用该方法将缓冲区剩余数据强制刷新出去。
3.3 特定方法
字符缓冲流提供了整行字符的处理方法。
String readLine():BufferedReader方法,从输入流中读取一行字符。void newLine():BufferedWriter方法,向输入流中写入行结束标志,下次写入的数据就会在下一行。
四、第四节 文件的处理
Java提供了File类,用于处理文件相关操作;File对象既可以用来生成文件,也可以用来生成文件目录。
1. File类
java.io.File类提供了获取文件基本信息及操作文件的方法。
1.1 构造方法
File(String pathname):pathname为文件名+文件路径名。File(String parent, String child):parent父路径名,child文件子路径名。File(File parent, String child):parent是一个文件对象,child文件子路径名。
1.2 文件名相关方法
String getName();:获取文件名。String getPath();:获取文件路径。String getAbsolutePath();:获取文件的绝对路径。String getParent();:获取文件父目录名称。boolean renameTo(File dest);:更改文件名。
1.3 文件测定方法
boolean exists;:判断文件对象是否存在。boolean canWrite();:判断文件对象是否可写。boolean canRead();:判断文件对象是否可读。boolean isFile();:判断文件对象是否是文件。boolean isDirectory();:判断文件对象是否是文件目录。boolean isAbsolute();:判断文件对象是否是绝对路径。
1.4 常用文件信息和方法
long lastModified();:获取文件最后修改时间。long length();:获取文件长度。boolean delete():删除文件对象指向的文件。
1.5 目录相关方法
boolean mkdir();:创建新目录。boolean mkdirs():创建新目录,与mkdir()不同的是,mkdirs可以一次性创建多层次的目录。String[] list(FilenameFilter filter):列出符合模式的文件名。
2. 随机访问文件
在文件不同位置进行读取操作,由RandomAccessFile类实现。
第八章 图形界面设计
一、第一节 AWT与Swing
1. 什么是GUI?
GUI(Graphical User Interface),又名图形用户界面;在java.awt包与javax.swing包下定义了多种用于创建图形用户界面的组件类。
2. 图形设计的步骤
一般设计图形用户界面有3个步骤:
- 选取组件
- 设计布局
- 设置响应事件
3. AWT与Swing的不同
- AWT组件定义在
java.awt包下,而Swing组件定义在javax.swing包下。 - 基于AWT的界面可能会应为运行而产生差异,而基于Swing的界面在任何平台上显示的效果都是一样的。
- 不包含本地代码的Swing组件被称为“轻量级”组件,而包含本地代码的AWT组件被称为“重量级”组件。
- 当重量级组件与轻量级组件共同使用时,如果组件有重叠,则重量级组件显示在最上面。
二、第二节 容器
1. 组件的分类
组件可以分为容器组件和非容器组件。
作为容器组件就是指可以包含其他组件的组件;而非容器组件则必须要包含在容器组件中。
容器组件又可以分为顶层容器组件和一般用途容器组件。
2. 容器组件
显示在屏幕上的组件都必须包含在某个容器中,有些容器可以嵌套,在这个嵌套的最外层,必须有一个顶层容器。
java为所有容器定义了父类Container,容器的共有操作都定义在Container类中。
3. 顶层容器
3.1 顶岑容器的分类和特点
在Swing中提供了4中顶层容器,分别为JFrame、JApplet、JDialog和JWindow;他们各自的特点如下:
- JFrame:
JFrame是一个带有标题行和控制按钮的独立窗口,有时候被称为框架。 - JApplet:
Applet是一个被包含在游览器中的窗口中。 - JDialog:
JDialog用于创建一个对话框。 - JWindow:
JWindow创建一个不带标题行和控制按钮的窗口。
3.2 使用注意
在创建容器对象后,他的大小为0,并且不可见;所以需要使用frame.pack()语句来调整窗口的大小,使用frame.setVisiable(true),来让容器可见。
4. 内容窗格
4个顶层容器,每个容器都有一个默认的内容窗格;处菜单外,顶层容器中的组件都放在这个内容窗格中。
- 顶层容器获取默认内容窗格的方法:
.getContentPane - 将组件放至内容窗格的方法:
add()
顶层容器默认的内容窗格的布局管理器是BorderLayout;而JPanel的默认布局管理器是FlowLayout。
注意:内容窗格可以嵌套,如一个面板中可以嵌套入另一个面板。
4. 面板
4.1 面板的分类
在javax.swing包中,面板被分为普通面板和滚动面板,他俩都是广泛运用的容器。
4.2 面板的特点
- 面板不能独立存在,必须要添加到其他容器内部。
- 面板可以嵌套。
4.3 普通面板的使用
Jpanel():创建一个普通面板,面板的默认布局时FlowLayout。JPanel(LayoutManager layout):创建一个带有指定布局管理器的普通面板。Compoent add(Compoent comp):将指定组件添加到面板或容器中。
4.4 滚动面板
JScrollPane是带有滚动条的面板,他是Container类的子类,且滚动面板中只能加入一个组件,所以一般都是先将各个组件添加进JPanel面板,然后将JPanel添加到JScrollPane滚动版面中。
4.4 创建滚动面板相关方法
创建滚动面板的方法(创建的滚动面板中包含滚动条)
JScrollPane():创建一个新的滚动面板。JSCrollPane(Compoent comp):创建一个显示指定组件的滚动面板,只要组件内容超过视图大小,就会显示垂直滚动条和水平滚动条。
AWT中滚动条组件的创建
-
ScrollBar():构造一个新的垂直滚动条。 -
Scrollbar(int orientation):构造一个具有指定方法的滚动条。...
三、第三节 标签及按钮
标签JLabel和按钮JButton都是swing中的组件。
1. 标签
1.1 JLabel的构造
JLabel():构造一个空标签。JLabel(Icon image):构造一个显示图标的标签。JLabel(String text):构造一个显示文字的标签。JLabel(Icon image, int horizontalAlignment):构造一个显示图标的标签,水平对齐方法由参数horizontalAlignment指定。JLabel(String text, int horizontalAlignment):构造一个显示文字的标签,水平对齐方法由参数horizontalAlignment指定。JLabel(String text, Icon icon, int horizontalAlignment):构造一个同时显示文字和图标的标签,水平对齐方法由参数horizontalAlignment指定。
注:horizontalAlignment的取值常类为:
JLabel.CENTER:居中对齐。JLabel.LEFT:左对齐。JLabel.RIGHT:右对齐。
1.2 JLabel中设置标签对齐的方法
void setHorizontalAlignment(int alignment):设置标签内容水平对齐的方法。void setVerticalAlignment(int alignment):设置标签内容垂直对齐的方法。
1.3 修改标签图标和文本的方法
void setIcon(Icon icon):设置标签图标的方法。void setText(String text):设置标签文本的方法。
2. 按钮
2.1 按钮的分类
经常用到的按钮分为JButton普通按钮、JToggleButton切换按钮、JCheckBox复选框按钮、JRadioButton单选框按钮,它们均是AbstractButton的子类。
它们都有着一些共有方法:
void addActionListener(ActionListener l):为当前按钮注册监听事件。void setEnabled(boolean b):禁用或启用button。void setText(String text):设置按钮的文本。setIcon(Icon defaultIcon):设置按钮的图标。
3. 切换按钮、复选按钮、单选按钮
切换按钮JToggleButton是具有两种状态的按钮,及选中状态和未选中状态。
JCheckBox复选按钮和JRedioButton都是JToggleButton的子类。
获取按钮的选中状态
在JToggleButton中定义获取按钮选中状态的方法:
boolean isSelected():如果当前按钮处于选中状态返回true,反之返回false。
可以注册的监听事件
JToggleButton、JCheckBox、JRedioButton这三种按钮因为有状态的切换,所以不仅可以注册ActionEvent事件侦听程序,还可以注册ItemEvent选项事件侦听程序。
4. 按钮组
按钮不仅可以单独存在,还可以多个按钮组成按钮组;当多个按钮被添加到按钮组之后,如果用户选中一个按钮,则其它按钮变为未选中状态。
JCheckBoxGroup与GRedioButtonGroup两个类分别注册了不同的事件侦听程序,实现了组中选一个按钮时,其他按钮变为未选中状态。
四、第四节 布局管理器
1. 布局管理器的定义和作用
定义:
布局管理器顾名思义就是用于容器的管理布局。
作用:
因为容器中有各个组件,那么组件的排列顺序就需要有人来管理;所以布局管理器的作用就是来管理各个组件的位置和大小。
2. 布局管理器的分类
根据各个布局管理器的管理方式不同,所以将各个布局管理器进行了分类。
- FlowLayout:流动布局管理器。
- BorderLayout:边框布局管理器。
- GridLayout:网格布局管理器。
- CardLayout:卡牌布局管理器。
- BoxLayout:盒子模型布局管理器。
- 空布局。
容器的默认布局管理器
顶级容器的默认布局管理器是BorderLayout;面板的默认布局管理器是FlowLayout。
3. FlowLayout(流动布局管理器)
3.1 FlowLayout的作用
FlowLayout定在java.awt包中,此布局管理器的方式是将组件逐个的放置在容器中的一行上,一行放慢之后就另起一行。
3.2 构造方法
FlowLayout():创建一个默认的FlowLayout布局管理器,居中对齐,默认水平和垂直间距为5个像素。FlowLayout(int align):创建一个FlowLayout布局管理器,对齐方式由align指定。FlowLayout(int align, int hgap, int vgap):创建一个FlowLayout布局管理器,对齐方式由align指定,垂直间距由hgap指定,水平间距由vgap指定。
align的取值
align的取值范围有FlowLayout.LEFT左对齐,FlowLayout.RIGHT右对齐,FlowLayout.CONTER居中对齐三种。
4. BorderLayout(边框布局管理器)
4.1 作用
BorderLayout是顶层容器的默认布局管理器,每个由BorderLayout管理的容器被分成5块区域;分别代表容器的上下左右中共5部分,分别用常量表示:
BorderLayout.NORTH:上部。BorderLayout.SOUTH:下部。BorderLayout.WEST:左部。BorderLayout.EAST:右部。BorderLayout.CENTER:中部。
4.2 构造方法
BorderLayout():构造一个组件之间没有间距的BorderLayout布局管理器。BorderLayout(int hgap, int vgap):构造一个BorderLayout布局管理器,并通过参数指定组件之间的间距大小。
4.3 获取
4.3 BorderLayout使用注意事项
顶层容器的默认布局管理器就是BorderLayout
- 在向容器中添加组件的时候,如果没有指定要添加到哪个区域,则默认放置到
Center区域;也可以在使用add()方法的时候添加到指定的区域。 - 在容器的每个区域只能加入一个组件,如果向其中一个区域加入多个组件,只有最后一个组件有效。
- 如果想往一个区域加入多个组件,那么可以先将组件加入到一个内部容器中(如面板),然后再将面板添加到顶层容器的某个区域。
- 如果某个区域没有使用,那么它的大小将变为0,其区域就被会center区域占据。
- 当窗口大小改变时,窗口中组件的相对位置不会改变,但是组件的大小会随之改变。
5. GridLayout (网格布局管理器)
5.1 定义
GridLayout是一种网格布局管理器,它将容器空间划分成若干行乘若干列的网格,组件依次放入其中,每个组件占据一格。
5.2 构造方法
GridLayout():创建一个只有一行的网格,网格的列数根据实际需要而定。GridLayout(int rows, int cols):创建具有指定行数和列数的网格布局管理器。GridLayout(int rows, int cols, int hgap, int vgap):创建具有指定行数和列数的网格布局管理器,并且指定垂直间距和水平间距。
5.3 注意事项
- 构造方法中,rows和cols其中一个值可以为0,但不能两个都为0.
- 每行网格从左到右一次填充,一行用完之后转入下一行。
- 当容器大小改变时,
GridLayout所管理的相对位置不会变化,但是组件大小会改变。
6. CardLayout(卡片布局管理器)
6.1 定义
CardLayout也是定义在java.awt包下的布局管理器,这是一种卡片式的布局管理器,它将容器的组件处理为一系列卡片,每一时刻只显示出其中的一张,而容器充当卡片的容器。
6.2 方法
构造方法
CardLayout():创建一个默认无间距的CardLayout布局管理器。CardLayout(int hgap, int vgap):创建一个带有指定间距的卡片布局管理器。
成员方法
void first(Container parent):翻转到容器的第一张卡片。void last(Container parent):翻转到容器的最后一张卡片。void next(Container parent):翻转到容器的下一张卡片,如果当前时最后一张,则翻转到第一张。void previous(Container parent):翻转到容器的上一张卡片,如果当前是第一张,则翻转到最后一张。void show(Container parent, String name):翻转到已添加到此布局的具有指定name的卡片,如果不存在则不发生任何操作。
7. BoxLayout(盒子模型布局管理器)
7.1 定义
BoxLayout是定义在java.awt包中的一种布局管理器,它将容器中的组件按水平方向拍成一行或按垂直方向排成一列。
当组件排成一行时,每个组件可以有不同的宽带;当组件排成一列时,每个组件可以又不同的高度。
7.2 方法
BoxLayout(Container target, int axis):创建一个将沿给定轴放置组件的布局管理器。target指定为哪个容器设置此BoxLayout布局;axis用于指定组件的排列方向,常用常量为BoxLayout.X_AXIS与BoxLayout.Y_AXIS表示水平方向排列或垂直方向排列。
7.2 Box类
在java.swing包中提供了Box类,使用这个类能够更加方便的创建具有BoxLayout的容器。
方法
static Box createHorizontalBox():使用水平方向的BoxLayout。static Box createVerticalBox():使用垂直方向的BoxLayout。
8. 空布局
8.1 定义
空布局指的是不使用布局管理器的情况,通过数值指定组件的位置和大小。
在使用空布局的时候首先要将容器的布局设置为null(setLayout(null)),然后调用组件的set Bounds()方法设置组件的大小和位置。
void setBounds(int x, int y, int width, int height):x与y设置组件的位置,width与height设置组件的宽和高。
五、第五节 事件处理
定义:用户在程序界面所进行的操作称为用户事件,对用户事件的响应称为事件处理。
1. 事件处理模型
1.1 什么是事件?
用户对程序组件进行的操作响应称为事件。
1.2 委托事件处理模型是怎么对事件进行处理的?
每种事件源可以发出多种不同类型的事件,在程序中为每个事件源指定一个或多个侦听者对事件进行侦听,每当数据源的某个事件发生,就会触发相应的侦听事件。
数据源:鼠标
事件:鼠标移动、鼠标双击、鼠标单击...
1.3 什么是侦听器?
侦听器是为了侦听用户与组件之间的交互情况,从而做出不同的相应。
1.4 侦听器的使用
为了接受并处理某个类用户事件,组件必须注册相应的事件处理程序,这种事件处理程序称为事件侦听程序,也成为侦听器。它是实现了对应侦听程序接口的一个类。
1.5 添加侦听器与移除侦听器
添加侦听器与移除侦听器都是在组件之上所进行的,所以以下两个方法需要组件对象来进行调用。
-
添加侦听器
void addActionListener(ActionListener l):方法参数就是要添加的侦听器。 -
移除侦听器
void removeActionListener(ActionListener l):方法参数就是要移除的侦听器,移除后用户对应的操作将不再被侦听到。
1.6 ActionEvent与ActionListener:star:
ActionEvent是事件,也就是一个组件有用的哪些事件。
ActionListener:则是事件对应的侦听器,能够侦听到组件的事件是否执行;侦听到事件执行后,做出某些动作。
组件、事件、侦听器之间的关系
组件和事件之间是多对多的关系;一个组件对应多个事件,一个事件可以由多个组件触发。
事件和侦听器之间的关系是一对一;即一个事件对应有一个侦听器,此侦听器就负责侦听对应的事件是否被触发。
关于事件相关的接口都在java.awt.event包与java.swing.event包下。
2. 事件的种类
**使用注意:**凡是需要接收并处理事件类对象的类(事件发生后需要执行的类),都需要实现事件对应的侦听接口。
3. 事件适配器
3.1 事件侦听模式
事件侦听模式允许为一个组件注册多个事件侦听。
3.2 事件适配器存在的意义
为了实现对组件事件的处理,需要实现Listener接口的类;然而在某些Listener接口中声明了很多抽象方法,为了实现这个接口,需要一一实现这些方法。然而在某些情况下我们只关心接口中的某个方法,但也不得不把Listener接口中的方法全部重写。
这样就比较麻烦,所以Java就提供了Adapter适配器,先有Adapter去实现各个Listener接口,然后重写接口中的方法(方法体为空)。因为Adapter是一个抽象类,所以我们在定义事件监听类的时候,直接继承Adapter适配器类,重写我们需要的方法就行了。
Listener接口
public interface MouseListener extends EventListener {
public void mouseClicked(MouseEvent e);
public void mousePressed(MouseEvent e);
public void mouseReleased(MouseEvent e);
public void mouseEntered(MouseEvent e);
public void mouseExited(MouseEvent e);
}
Adapter适配器类
public abstract class MouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener {
public void mouseClicked(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseWheelMoved(MouseWheelEvent e){}
public void mouseDragged(MouseEvent e){}
public void mouseMoved(MouseEvent e){}
}
3.3 接口对应的适配器
JDK中并没有为所有的监听器接口都提供相应的适配器类。
六、第六节 绘图基础
绘图过程说明
- 在平面上绘图或显示文字,首先需要确定一个平面坐标系。
- 显示屏上的一个长方形区域为程序的绘图区域,坐标原点(0,0)位于区域的左上角。
- 一个坐标点(x,y)对应屏幕窗口中的一个像素。
- 设置绘图区域的宽和高,就能够确定绘图区域的大小。
1. 颜色
1.1 使用的类
Java中使用java.awt包下的Color类来定义和管理颜色。
1.2 构建颜色的方法
使用Java中预定义的颜色
自定义RGB组合确定颜色
通过三原色红、绿、蓝三种颜色的组合,来产生新颜色。
Color color = new Color(float r, float g, float b)
2. 字体
2.1 绘制字体的方法
画图对象调用
-
drawChars(char data[], int offset, int length, int x, int y)使用此图形上下文的当前字体和颜色,从数组
data的下标索引offset处,取length个字符,从图形的x和y处开始绘画。 -
void drawString(String str, int x, int y)在指定位置显示字符串
str。 -
drawBytes(byte data[], int offset, int length, int x, int y)使用与第一个方法相同。
Font类预定义文本字体
-
Font(String name, int style, int size)根据指定的字体名称(如宋体)、样式(斜体、粗体)和字号创建一个新的Font对象。
-
setFont(Font f):通过组件的setFont()方法,将预定于的文本字体设置到组件中。
3. GrapHics类的基本功能
3.1 GrapHics的定义
GrapHics是java.awt包下的类,用于显示和管理图形信息,是所有图形上下文的抽象父类。
3.2 功能
建立字体、设置显示颜色、显示图像和文本、回值和填充几何图形等。
3.3 Graphics的作用
- 控制组件的颜色和显示文本的字体。
- 在组件上绘制图形。
3.4 绘图模型
组件上的绘图模型主要分为两类——正常模式和异或模式。
-
正常模式
正常模式下,后绘制的图形会覆盖掉先绘制的图形。
-
异或模式
异或模式下,当前绘制的颜色、先前回值的颜色以及所选定的颜色之间会进行某种处理,得到新的颜色进行绘制。
Graphics设置绘图模式的方法:
void setPaintMode():将此图形的绘图模式设置为正常模式。默认正常模式。void setXORMode(Color c1):将图形的绘图模式设置为异或模式,c1指定颜色。
3.5 注意事项
- 异或模式下,如果使用同一颜色绘制两遍,则相当于擦除第一次绘制的图形,即恢复成原来的状态。
- 所有的绘制都必须通过一个图形对象完成。
- 可以在框架(JFrame)中直接显示文本信息,也可以直接在框架中绘图。
- 在某个组件(JComponent)中绘图,应该重写
paintComponent(Graphics g)方法,在该方法中进行绘图。
3.5 Graphics中的绘图方法
画圆方法
drawPolygon()fillPolygon
其他方法自行查阅。
4. Graphics2D绘制
为了解决图形对象的局限性,Java引入了一个Graphics2D类,增加了许多状态属性,扩展了Graphics的绘图功能。
4.1 图形状态属性
Graphics2D类中定义了几种方法,用于添加或改变图形的状态属性。
stroke属性
-
作用
stroke属性控制线的宽度、笔形样式、线段连接方式和短划线图案。 -
使用
创建
BasicStroke对象,然后再调用setStroke()方法即可设置stroke属性。 -
构造方法
BasicStroke(float width):指定线的宽度。
paint属性
-
作用
paint属性控制填充效果。 -
使用
先调用
GradientPaint()方法确定填充效果,再使用setPaint()方法继续设置。
transform属性
-
作用
该属性用来实现常用的图形平移、缩放和斜切等变换操作。
-
使用
首先创建
AffineTransform对象,然后调用setTransform方法,设置transform的属性;最后使用具有指定属性的
Graphics2D对象绘制图形。 -
构造方法
AffineTransform()
clip属性
-
作用
clip属性用于实现建材效果。
composit属性
composit属性设置图形重叠区域的效果。
4.2 Graphics2D类的绘图方法
Graphics与Graphics2D的不同
Graphics2D仍然保留着Graphics的绘图方法,同时增加了许多新的方法。新方法将几何图形作为一个对象来绘制。
几何图形对象
Line2D:线段类RoundRectangle2D:圆角矩形类。Ellipse2D:椭圆类。Arc2D:圆弧类。QuadCurve2D:二次曲线类。CubicCurve2D:三次曲线类。
Graphics2D类的使用方法
使用Graphics2D类的新方法画一个图形的步骤通常是:
- 现在重画方法
paintComponent或paint()中,把参数对象g强制转换为Graphics2D类型对象。 - 用上述图形类提供的静态方法
Double()创建该图形的对象。 - 最后以图形对象为参数调用
Graphics2D对象的draw()方法绘制这个图形。
第九章 Swing组件
一、第一节 组合框和列表
1. 组合框
1.1 组合框的定义
组合框(JComboBox),是一个下拉菜单,它拥有两种形式——不可编辑和可编辑的。
对于不可编辑的JComboBox,用户只能在现有的选项列表中进行选择;对于可编辑的JComnoBox,用户既可以在现有的选项中选择,又可以输入新的内容。
1.2 构造方法
JComboBox():创建一个没有任何可选项的默认组合框。JComboBox(E[] items):创建一个带有初始选项的组合框,初始选项就是items数组中的元素。
1.3 设置组合框可编辑状态
在组合框对象创建后,默认是不可编辑得;可以通过setEnabled(boolean b)方法将其设置为可编辑的。
1.4 JComboBox常用方法
addItem(E item):添加选项末尾添加新选项。Object getSelectedItem():返回当前所选项。removeItemAt(int anIndex):删除指定索引处的选项。- ...
1.5 组合框事件
组合框上的用户事件既可以通过ActionListener处理,也可以通过ItemListener处理。
用户输入项目后按<Enter>键,对应的接口是ActionListener,而用户选中选项,对应的接口是ItemListener。
2. 列表(JList)
2.1 定义
列表JList是一个可供用户进行选择的一系列可选项。
2.2 构造
JList():构造一个空列表。JList(final E[] listData):构造一个列表,列表的可选项又对象数组listData指定。
2.3 列表事件侦听
当用户在列表上进行选择时,将引发ListSelectedEvent事件。
在JList中,提供了addListSelectionListener(ListSelectionListener listener)方法,用于注册对应的事件侦听程序。
ListSelectionListener 接口中只包含一个方法void valueChanged(ListSelectionEvent e);,当列表的当前选项发生变化时,将会调用该方法。
2.4 常用方法
int getSelectedIndex():返回所选项第一次出现的索引;如果没有所选项,则返回-1。E getSelectedValue():返回所选的第一个值,如果选择为空,则返回null。void setVisibleRowCount(int visibleRowCount):设置不使用滚动条可以在列表中显示的首选行数。
2.5 列表使用注意事项
-
可以使用
JList中定义的setModel(ListModel<E> model)方法,设置新的列表选项。 -
当列表可选项较多时,可以将列表对象放入
JScrollPane滚动窗口中,以提供滚动功能。 -
列表既支持单项选择,又支持多项选择;可以使用
JList中定义的setSelectionMode(int selectionMode)方法,对列表的选择模式进行设置。selectionMode常量:
-
ListSelectionModel.SINGLE_SELECTION只能进行单项选择。
-
ListSelectionModel.SINGLE_INTERVAL_SELECTION可多项选择,但多个选项时必须连续的。
-
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION可以多项选择,且多个选项之间可以间断的,设置默认选择模式。
-
二、第二节 文本组件
文本组件的定义
文本组件可用于显示信息和提供用户输入功能。
文本组件的分类和共有
分类
在Swing中提供了文本域JTextField、口令输入区JPasswordField、文本区JTextArea等多个文本组件,这些文本组件都有一个共同父类——JTextComponent。
共有方法
String getSelectedText():从文本组件中提取被选中的内容。String getText():从文本组件中提取所有文本内容。String getText(int offs, int len):从文本组件中获取指定范围内的文本内容。void select(int selectionStart, int selectionEnd):在文本组件中选中指定的起始位置和结束位置之间的文本内容。void setText(String t):这只文本组件中的文本内容boolean requestFocusInWindow():获取当前组件的输入焦点。- ...
1. 文本域(JTextField)
1.1 定义
文本域是一个单行的文本输入框,用于输入少量文本。
1.2 构造方法
JTextField():构造一个空的文本域。JTextField(int columns):构造一个带有指定列数的空文本域。JTextField(String text):构造一个带有初始文本的文本域。- ...
1.3 常用方法
-
synchronized void addActionListener(ActionListener l)为当前文本域添加指定的监听器,接受操作事件。
-
synchronized void removeActionListener(ActionListener l)移除当前文本域的监听器。
-
void setFont(Font f):设置字体大小。 -
void setHorizontalAlignment(int alignment)设置文本的水平对齐方式。
1.4 文本域使用注意事项
在构造方法中指定的列数是一个希望数值;由于组件的大小和位置受布局管理器的决定,所以指定的数值有可能不准确。
2. 文本区
2.1 定义
文本区是要给多行多列的文本输入框。
2.2 构造
JTextArea():构造一个空的文本区。JTextArea(String text):构造一个显示初始字符的文本区。JTextArea(String text, int rows, int columns):构造一个显示初始字符,并且指定文本区的行数和列数。
2.3 文本区常用方法
void append(String str):追加字符到文本区中。void insert(String str, int pos):将指定文本插入到文本区的pos特定位置处。void replaceRange(String str, int start, int end):将指定起始位置上的文本替换为str新文本。
2.4 文本区事件
通常时在文本区旁提供一个按钮,当用户点击时表示输入完成;我们只需要对按钮的点击事件进行监听即可。
2.5 文本区的使用注意事项
- 构造文本区时指定的行数和列数还是受组件布局管理器的影响,实际数值有可能会出现偏差。
- 文本区本身不带滚动条,如果文本区内容较多,可以讲其放入
JSrollPane滚动窗格中。
三、第三节 菜单组件
菜单组件的分类
菜单分为下拉式菜单和弹出式菜单两种。
1. 菜单栏和菜单
1.1 菜单栏的定义
菜单栏是窗口的主菜单,用来包容一组菜单。
1.2 菜单的定义
菜单是最基本的下拉菜单,用来包容一组菜单项或子菜单。
1.3 菜单栏的构造方法
JMenuBar(),用于构建菜单栏。
1.4 在框架窗口中放置菜单栏
方法:void setJMenuBar(JMenuBar menubar),将菜单栏放置窗口的上方。
1.5 菜单的构造方法
JMenu():构造一个没有文本的菜单。JMenu(String s):构造一个带有指定标签的菜单。JMenu(String s, boolean b):构造一个具有指定便签的菜单,b代表该菜单是否可以分离。
1.6 将菜单加入菜单栏中
使用JMenuBar提供的JMenu add(JMenu c)方法,放菜单加入菜单栏中。
2. 菜单项
2.1 菜单项的定义
如果将整个菜单系统看作是一棵树,那么菜单项就是这棵树的叶子,是菜单系统最下面的一级。
菜单项是挂载在菜单下的。
2.2 构造方法
JMenuItem():构造一个空的菜单项。JMenuItem(Icon icon):构造一个具有指定图标的菜单项。JMenuItem(String text):构造一个具有指定文本标签的菜单项。JMenuItem(String text, Icon icon):构造一个具有指定图标和文本的菜单项。JMenuItem(String text, int mnemonic):构造一个具有指定文本和快捷键的菜单项;mnemonic指定快捷键。
2.3 设置菜单项的快捷键
在菜单被创建后,还可以通过JMenuItem类提供的void setMnemonic(char mnemonic)方法,设置菜单项的快捷键。
2.4 在菜单项中加入分割线
Menu类中定义的方法
void addSeparator():在菜单项后加入分割线。void insertSeparator(int index):在指定的索引位置处加入菜单项的分割线。
java.swing包中的JSepatator类
JSeparator():创建一个分割线实例,然后通过JMenu类中的Component add(Component c)方法,将分割线实例加入菜单。
2.5 菜单项选中事件
当菜单中的菜单项被选中的时候,将会引发一个ActionEvent事件,因为在定义菜单项的时候,可以其注册ActionListener监听器,以便做出响应。
awt包中的MenuItem类
addActionListener(ActionListener l)
JMenuItem类
void addMenuKeyListener(MenuKeyListener l)
3. 复选菜单项和单选菜单项
3.1 定义
复选菜单项和单选菜单项是两种特殊的菜单项,复选菜单项前有一个小方框,单选菜单项前有个小圈圈。
3.2 复选、单选菜单项的选中说明
由于复选菜单项与单选菜单项具有选中与未选中两种状态,所以在其各自的构造方法中,只用boolean参数指定菜单项的初始状态。(默认未选中)
3.3 复选菜单项构造方法
JCheckBoxMenuItem():创建一个空白复选菜单项。JCheckBoxMenuItem(Icon icon):创建一个带有图标的复选菜单项。JCheckBoxMenuItem(String text):创建一个带有文字标签的复选菜单项。JCheckBoxMenuItem(String text, Icon icon, boolean b):创建一个带有文字标签和图标的复选菜单项,b参数指定该菜单项默认状态是否被选中。
3.4 单选菜单项构造方法
JRadioButtonMenuItem():创建一个空白的单选菜单项。JRadioButtonMenuItem(String text, Icon icon):创建一个带有文字标签和图标的单选菜单项。JRadioButtonMenuItem(String text, Icon icon, boolean selected):创建一个带有文字标签和图标的单选菜单项,selected参数指定该菜单项默认状态是否被选中。
3.5 菜单项事件
当菜单项的状态发生改变时,会引发ItemEvent事件,可以使用ItemListener接口中的itemStateChanged()方法,处理菜单项的状态改变事件。
3.6 菜单系统的整体创建过程
- 创建菜单栏,将其通过
setMenuBar()方法,加入框架中。 - 创建菜单,通过
add()方法添加到菜单栏中。 - 创建菜单项,通过
add()方法添加到菜单中。
四、第四节 对话框
1. 对话框
1.1 定义
对话框是一个临时的可移动的窗口,且要依赖于其他窗口;当他依赖的窗口消失或最小化时,对话框也将消失;当依赖窗口还原时,对话框也将自动恢复。
1.2 对话框的大致实现过程
首先要创建一个窗口类,再创建一个对话框类,且让对话框依赖于窗口。
1.3 对话框的分类和特点
分类
对话框分为强制型和非强制型。
特点
强制型的对话框被关闭前,其它窗口无法接受任何形式的输入,也就是该对话框不能中断,这样的窗口称为模式窗口。
非强制型对话框可以终端对话过程,去响应对话框之外的事件。这样的窗口称为无模式窗口。
1.4 对话框的构造方法
JDialog():创建一个空白对话框。JDialog(Dialog owner, String title, boolean modal):创建一个具有指定标题和指定所有者的对话框,modal参数指定对话框是有模式窗口还是无模式窗口。JDialog(Frame owner, String title, boolean modal):创建一个具有指定标题和指定所有者的对话框,modal参数指定对话框是有模式窗口还是无模式窗口。
1.5 对话框的显示和隐藏
刚刚创建的对话框是不可见的,需要调用setVisble(true)方法才能将其显示出来。
当对话框不需要显示的时候,调用setVisble(false)方法可以隐藏对话框。
注:对话框也是顶层容器,可以向对话框的内容窗格中添加各种组件。
2. 标准对话框
JDialog类通常用于创建自定义的对话框;在swing包下还提供了JOptionPane类,此类用于显示标准的对话框。
2.1 标准对话框的分类
-
确认对话框,显示问题,要求用户进行确认(yes/no/cancel)
static int showConfirmDialog(Component parentComponent, Object message) -
输入对话框,提时用户输入。
String showInputDialog(Component parentComponent, Object message) -
信息对话框,显示信息,提示用户。
static void showMessageDialog(Component parentComponent, Object message) -
选项对话框,显示选项,要求用户选择。
static int showOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue)
3. 文件对话框
3.1 定义
文件对话框时专门用于对文件或目录进行浏览和选择的对话框。
3.2 文件对话框构造方法
JFileChooser():构造一个执行用户默认目录的文件对话框。JFileChooser(File currentDirectory):使用给定的File作为路径来构造一个文件对话框。JFileChooser(String currentDirectoryPath):构造一个给定路径的文件对话框。
住:刚刚创建的文件对话框是不见的,需要调用以下方法将其显示,在让其显示的时候,也就定义了文件对话框的类型。
3.3 显示并确定文件对话框的类型
int showOpenDialog(Component parent):弹出一个“打开”类型文件对话框。int showSaveDialog(Component parent):弹出一个“保存”类型文件对话框。
3.4 获取用户所选文件的方法
当用户进行文件选择后,可以通过File getSelectedFile()方法获取用户所选文件。(JFileChooser类的方法)
第十章 多线程
一、第一节 线程和多线程
1. 线程的概念
1.1 什么是进程
进程就是程序在处理机中的一次运行,简单来说,进程就是计算机中运行的应用程序。
1.2 进程的特点
在进程运行的时候,计算机会为其分配资源,如CPU、内存、端口等;不同进程所占用的系统资源相对独立。
1.3 什么是线程
线程是进程中的最小执行单位。
1.4 线程的特点
- 线程是比进程更小的执行单位。
- 线程必须栖身为某个进程之中,由进程触发执行。
- 属于同一进程的所有线程共享该进程的系统资源。
- 线程之间切换的速度要比进程之间切换快得多。
- 不同线程所执行的代码可以相同也可以不相同;不同线程之间的访问数据可以相同也可以不相同。
- 使用多线程可以在线程之间共享数据和资源,而进程不能实现。
- 多线程适用于开发有多种交互接口的程序。
1.5 多线程的优点
多线程可以使系统资源的利用率得到提高,也能够提升整个程序的执行效率。
2. 线程的状态
2.1 线程状态
java的线程是由java.lang包下的Thread类来实现的;当生成一个Thread类对象的时候,及创建了一个线程,通过该对象,可以控制线程的启动、终止、或挂起线程。
Thread类中的run()方法,称为线程体,里面就是线程要执行的程序。
线程的状态
线程一共有4中状态,新建、可运行、阻塞、死亡。
2.2 新建
线程对象通过Thread类创建,此时还处于未运行状态,但是已经有了相应的内存空间和其他资源。
2.3 可运行状态
此时线程已经启动,在这种状态下线程有可能正在运行,也有可能没有运行,处于等待状态;只要CPU有空闲,那么处于等待状态的线程马上就会运行。
处于等待状态的线程都排在一个就绪队列中。
可运行状态下,正在运行的线程处于运行状态,等待运行的线程处于就绪状态。
2.4 死亡
线程死亡的原因有两个:一是线程体执行完毕,线程正常死亡,二是当线程遇到异常退出便进入了死亡状态。
2.5 阻塞
一个正在执行的线程因特殊原因被暂停执行,进入阻塞状态,
阻塞线程不能进入就绪队列,必须等阻塞状态移除,才可进入就绪状态。
2.6 线程中断
在Thread类中提供了方法可以手动中断线程的执行:
void interrupt():中断当前线程的执行。boolean interrupted():检测并中断当前线程。boolean isInterrupted():检测当前线程是否中断。
二、第二节 创建线程
创建线程的两种方法,一是继承Thread类,二实现Runnable接口。
1. 继承Thread类创建线程
java.lang包下的Thread类是Java中表示线程的类,如果将一个类定义为Thread的子类,那么这个类的对象就可以用来表示线程。
1.1 Thread构造方法
-
Thread(Runnable target):通过Runnabel对象,构造一个Thread线程对象。 -
Thread(ThreadGroup group, Runnable target, String name)group表示当前构造的Thread对象属于哪个线程组。target表示当前线程任务对象。name设置当前线程对象的名称。
PS:Thread类本身也是Runnable接口的实现类。
1.2 Thread创建线程的步骤
- 自定义类,继承
Thread类。 - 重写
run()线程体。 - 创建当前自定义类的对象,调用
start()方法启动线程。
PS:只要是Thread类的子类,都是线程类。
2. 实现Runnable接口创建线程
Runable是Java中用以实现线程的接口,任何实现线程功能的类都必须实现此接口;Thread类本身也实现了Runnable接口。
2.1 Runnable接口的结构
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
在Thread接口中只有一个run()方法,这个方法就是线程的线程体。
2.2 Runnable创建线程的步骤
- 自定义类,实现
Runnable接口。 - 重写
run()方法。 - 创建实现类对象,通过
Thread(Runnable target)构造函数创建Thread对象,并通过Thread对象的run()方法启动线程。
个人理解:在我的理解看来,Runnable接口的实现类相当于一个线程任务,想要执行这个线程任务,还是需要Thread类来启动执行这个线程任务。
3. 创建线程两种方法的适合条件
其实不管用那种方法都可以用来创建线程类,但是需要注意的是Java是单继承制;也就是说一个子类只能直接继承一个父类。所以如果在创建线程类的同时还要继承其他父类,则用Runnable接口的方法比较好。
三、第三节 线程的基本控制
1. 线程的启动
通过Thread类的run()方法启动。
2. 有关线程的常用方法
void start():启动线程。void run():线程体,也就是线程启动后要执行的方法。void yield():强制终止线程的执行。boolean isAlive():测试当前线程是否在活动。void sleep(long millis):是线程休眠一段时间。void wait():使线程处于等待状态。
3. 线程的调度
3.1 线程调度说明
虽然就绪线程可以运行,但并不意味着当前线程就能够立刻运行。
在单核CPU的计算机中,CPU同一时间只能分配给一个线程。
在Java中,线程的调度通常是抢占式,而不是时间片式。抢占式调度指的是可能有多个线程准备运行,但是只有一个在真正运行。只有运行着的线程执行完毕,或因原因阻塞,另一个高优先级的线程才能够抢占CPU从而运行。
3.2 线程调度的优先级策略
- 优先级高的限制性。
- 每个线程会自动分配一个默认的优先级,子类默认继承父类的优先级。
- 同优先级的线程按 “先进先出” 的调度原则。
Thread类有3个与线程优先级相关的静态常量。
MAX_PRIORITY:最高优先级,值为10。MIN_PRIORITY:最低优先级,值为1。NORM_PRIORITY:默认优先级,值为5。
3.3 线程优先级相关方法
Thread类中:
void setPriority(int newPriority):重置线程优先级。int getPriority():获取当前线程的优先级。void yield():停止当前正在执行的线程。
3.4 线程调度处理说明
所有被阻塞的线程按次排序,组成一个阻塞队列;而所有就绪但未运行的线程则根据优先级进入一个就绪队列。
当CPU空闲时,如果就绪队列不为空,则队列中的第一个具有最高优先权的线程将运行。
当一个线程被抢占而停止运行是,它的运行状态被改变,并放到就绪队列的尾列。
一个被阻塞的线程就绪后,通常也放置就绪队列的尾列。
3.5 sleep方法说明
Sleep()是Thread类的静态方法,这个方法只保证当前休眠的线程在一定的时间后回到就绪状态,至于是否能够得到CPU的运行权,则要视线程调度而视,所以通常实际暂停时间比指定时间长。
4. 结束线程
4.1 线程的三种结束方法
- 线程的
run()方法执行完毕,线程自动死亡。 - 线程遇到异常被动死亡。
- 使用
interrupt()方法中断当前线程的执行。
PS:Thread currentThread()获取当前线程。
5. 挂起线程
暂停一个线程也称为挂起,在挂起后,必须重新唤醒线程进入运行状态。
5.1 挂起线程的方法
sleep()
sleep()方法用于暂时停止线程的运行,一段时间后线程会自动醒来;醒来后的线程不会立刻执行,要看线程调度的安排。
wait()、notify()、notifyAll()
wait()方法用于当前线程等待,直到其他对象调用此线程对象的notify()方法或者notifyAll()方法,唤醒等待的线程。
join()
join()将引起现行线程等待,直至join()方法所调用的线程结束。
比如在B线程中调用A线程的join()方法,那么需要等A线程执行完毕后,才会继续执行B线程。
四、第四节 线程的互斥
1. 什么是线程的互斥
线程的互斥指在同一时间,只能有一个线程访问共享数据,具有排他性和唯一性。
所以需要一种机制来保证线程操作的完整性,要么一段代码全部执行成功,要么都不执行。(原子性操作)
2. 对象的锁定标志
2.1 对象互斥锁的概念
在Java语言中引入了 “对象互斥锁” 的概念,也称监视器;使它用来实现不同线程对共享数据操作的同步。
2.2 对象互斥锁的作用
“对象互斥锁” 用来阻止多个线程同时访问同一个变量。
2.3 对象互斥锁的实现
在Java中有两种方法可以实现 “对象互斥锁”:
- 使用
volatile关键字来声明共享数据变量。 - 使用
synchronized关键字操作共享数据的一个方法或代码。
PS:在同一时刻只能有一个任务访问的代码区称为临界区。
2.4 锁的返回
当持有锁标志的线程执行完synchronied包含的程序块后,这个锁标志将会自动返还。
用synchronied标识的代码段或方法即为 “对象互斥锁” 锁住的部分。
如果一个程序内有两个或以上的方式使用synchronized标志,则它们在同一个 “对象互斥所” 的管理下。
2.5 synchronized效率
使用synchronized关键字锁在方法上要比锁住某个代码块的效率要低一点。
使用synchronized关键字的程序也叫做同步代码块
五、第五节 线程的同步
1. 什么是线程的同步
线程的同步指的是在线程互斥的基础上,实现线程的有序访问,最终让程序正确执行。
2. 使用方法
在Java语言中,可以用wait()、notify()与notifyAll(),来协调线程之间的执行速度,达到有序访问的效果。
2.1 wait方法
wait()方法让当前线程等待,进去等待队列,并释放当前线程所持有的锁对象。
2.2 notify与notifyAll
notify与notifyAll方法则是唤醒使用wait()等待的线程,并将它们移入抢锁队列中,抢到锁则执行线程。
2.3 使用注意
在使用一个对象的wait()、notify()与notifyAll()方法时,必须持有该对象的所标志。
2.4 终止等待线程的方法
当一个线程调用了wait()方法后,这个线程就进入了等待状态,等待被线程唤醒。
而将等待线程唤醒的方法有两种,一种是使用notify()方法,而另一种是使用interrupt()方法。
完!