Java基础
本文最后更新于:2023年2月28日 下午
全局介绍
JVM/JRE/JDK
命名
-
.xml文件
-
groupId: 域名(顶级域名.公司.组织.个人.功能板块)
-
artifactId: 功能模块
-
-
命名规范
-
包:域名(顶级域名.公司.组织.个人.功能板块)
-
类:大驼峰
-
变量:小驼峰
-
常量:大写下划线连接
-
机制
- 引用机制
基本数据类型:值传递(不与其它变量共享值)
变量:引用传递(传递存储地址)
- 垃圾回收机制
JRE自动销毁对象释放内存空间
基本语法
关键字f/s/a/d/t
关键字 | 意义 | 补充 |
---|---|---|
final | 声明对象构建之后,值不可变 | 可用于声明不被继承的类/不被重写的方法/引用不被更改的变量 |
static | 声明静态域、静态方法 | 静态域(静态变量/静态常量):所有对象共享,内存中占一份 静态方法:不需要实例化,可直接调用,与对象无关 静态导入:如 import static java.lang.System -> System.out.println = out.println 直接使用类的静态方法和静态域 |
abstract | 抽象类/方法 | 抽象类:含有一个或多个抽象方法的类,不能创造实例对象,可以被子类继承并重写其抽象方法 |
default | 默认 | |
this | 当前对象的引用 | 可以通过this,在实例方法或构造函数中引用当前对象的成员变量 |
关于抽象类的代码示例:
1 |
|
访问限制修饰符
Access level modifiers
关键字 | 意义 | 补充 |
---|---|---|
public | 所有类可见 | top level ,即独立的源文件,只有类/接口/枚举/注解,支持创建为顶级的独立源文件,不存在顶级的方法/变量/常量等 |
private | 本类可见 | member level ,类的私有静态变量,类的每一个对象内部均可访问,但外部无法访问 |
protected | 本包/所有子类可见 | member level |
package-private | 无修饰符的默认声明,仅本包内可访问 | top level/ member level ,Package级允许源文件名与类型名称不同(但是禁止使用),Public级别则不允许 |
声明
-
包声明
package
-
类声明
class
-
方法声明
方法签名:方法名称/参数列表(参数个数/参数类型)组成,其不同保证编译成功
方法重载:同名不同参方法
-
访问限制修饰符
-
返回值类型
无返回值:void
-
方法名
-
参数列表
可变长度参数: <数据类型>…
-
{<代码块>}
-
数据类型
Java的变量类型分为2种。基本类型(原始类型)和引用类型。
Java提供了8种基本类型。6种数字类型(4个整数型,2个浮点型),1种字符类型,还有1种布尔型。
- 十进制,表示指数 10^2 = e2
- 十六进制,前缀0x,表示指数 0.125 = 2^-3 = 0x1.0p-3
- 支持下划线 ‘_’ 分隔提高代码可读性
Type | Def | Remark | Cate |
---|---|---|---|
byte | 8位整数 | 4个整数型 | |
short | 16位整数 | 4个整数型 | |
int | 32位整数 | 4个整数型 | |
long | 64位整数 | 后缀L | 4个整数型 |
float | 单精度浮点 | 后缀f/F | 2个浮点型 |
double | 双精度浮点 | 后缀d/D,可省略 | 2个浮点型 |
boolean | 布尔 | 仅具有true/false,无法与0/非0整型替换 | 1种布尔型 |
char | 字符 | 单字符,单引号声明 | 1种字符类型 |
String | 字符串 | 多字符,双引号声明 | 非基本数据类型,封装类,字符串类型 |
enum | 枚举 | 自定义,包含有限个命名的值 | 非基本数据类型 |
关于常量(不可变对象)与变量
1 |
|
以上代码的运行逻辑为:
如果运行这段代码会发现先输出
“abc”
,然后又输出“abcde”
,好像是str
这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str
,并把“abc
”赋值给str
,然后在第三行中,其实JVM又创建了一个新的对象也名为str
,然后再把原来的str
的值和“de”
加起来再赋值给新的str
,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str
实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。
String的可变数据类型 | |
---|---|
StringBuilder | 不支持并发操作,线程不安全,单线程下速度快 |
StringBuffer | 支持并发操作,线程安全,适用于多线程 |
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全
类型转换
- 小向大转换,可直接转换 (例如int to double)
- 大向小转换,必须声明强制转换 (例如double to int)
- 当操作数的类型不同时,自动向高精度类型转换
数组
两种创建方式
-
创建指定长度的空数组(new)
-
创建确定元素的数组
多维数组创建
多维数组元素访问
运算符
operations | mean |
---|---|
++i | i +=1; return i |
i++ | return i; i +=1 |
&& | 与 |
|| | 或 |
^ | 异或 |
?: | 三目运算符(条件判断?真:假) |
控制流
statement | use | mean |
---|---|---|
for | for(初始条件; 终止条件; 循环步长){} | 循环 |
forEach | for(变量 : 数组){} | 增强型循环 |
while | while(终止条件){} | 循环 |
do/while | do{}while(终止条件) | 循环 |
if/then/else ;if/else |
面向对象
关键字
关键字 | 意义 | |
---|---|---|
extends | 子类 extends 超类 | |
implements | 类 implements 接口 | |
super | 代表当前类的超类,指示编译器调用超类方法/构造器 | 不能理解为是指向父类的引用,虽然实例化时会调用超类构造函数,但并不会创建超类对象。因此,不存在超类对象。 |
构造器
1 |
|
构造器的创建
- 编译器自动为没有显式声明构造函数的类,创建一个无参构造函数(no-argument constructor)
但,当类显式声明了有参构造函数,编译器将不再自动创建无参构造函数 - 一个类可以声明多个构造函数基于不同构造函数创建对象并初始化属性值
- 在构造函数中,通过super调用超类构造函数语句必须置于构造函数第一行;父类无无参构造函数必须显示调用父类有参构造函数
构造器的使用
-
构造器名字与类名相同,使用时在构造器前面加上
new
操作符构造一个对象 -
为了构造的对象多次使用,通过变量引用此对象。new操作符为对象分配内存,并返回该对象的内存地址给变量
-
数组初始化
1
2
3
4
5
6
7
8
9
10
11
12/* 整型 */
int[] a; //只声明数组a,没有初始化
int[] a = new int[5]; //初始化为默认值,int/byte/short/long型为0
int[] a = {1,2,3,4,5}; //初始化为给定值
int[] a = new int[] {1,2,3,4,5}; //初始化为给定值
int[] a = new int[5] {1,2,3,4,5}; //错误,如果提供了数组初始化操作,则不能定义维表达式
/* 布尔型 */
boolean[] boolArray=new boolean[5]; // 初始化为默认值,bool型为false
/* 浮点型 */
double[] doubles = new double[5]; // 初始化为默认值,float/double型为0.0
实例化
类加载实例化过程(Order of Initialization)
-
首先,基于类的加载顺序(先加载子类的父类),完成类的加载
类的加载:执行静态相关操作。即,按顺序初始化static变量(置于堆空间的静态区共享使用),执行static代码块。
-
其次,基于类的加载顺序(先加载子类的父类),执行类中初始化属性操作
初始化属性:按顺序执行属性声明及构造函数。
1 |
|
访问器与更改器
由于对类属性的封装,其数据改变需要编写对外的访问器方法。
1 |
|
继承
- 每个类只能拓展于一个子类
- 子类必须满足超类特性。因此,逻辑上,能够构造初始化子类的前提,是必须能够构造初始化超类
-
overriding/hiding:
支持在子类中声明一个与超类中方法签名相同的,新实例方法,从而overriding覆盖超类方法(方法的重写),重写方法的访问范围,必须大于等于超类声明的范围
支持在子类中声明一个与超类中方法签名相同的,新的静态方法,从而hiding隐藏超类静态方法
多态
–作业–
1 |
|
向上转型
向上转型(upcasting),(隐式转换,implicit casting)
- 隐式的上转型,子类一定具有超类的特性,因此编译器可自动实现类型转换
- 接口不能直接实例化,但是可以通过向上转型将其实现类实例化。
- 向上转型是将子类对象赋给父类引用,限制了子类对象的行为类型,只能够调用子类重写的方法。
1 |
|
1 |
|
1 |
|
向下转型
向下转型(downcasting),(显式转换,explicit casting)
- 显式的下转型,超类未必一定是子类,因此需显式声明强制转换,且只有运行时才能知道错误
- 即父类强转子类,是将父类引用的子类对象重新赋给子类引用
1 |
|
接口
-
一个接口可以扩展自任意数量的接口,一个类可以实现多接口
-
仅可包含方法(抽象方法,默认方法和静态方法)与常量(公有常量)
- 方法与常量默认声明为(无需重复编写):
public static final
,可使用default
声明默认方法,支持package
修饰符(顶级)
- 方法与常量默认声明为(无需重复编写):
-
由普通的类来实现接口,必须将接口所有抽象方法重写
由抽象类来实现接口,则接口的方法可根据需要选择是否重写。
继承实现接口的抽象类时,子类必须重写抽象类未实现的方法。
抽象类的作用即是:
将接口中不需要使用抽象方法交给抽象类完成,这样接口实现类只需要对接口需要方法进行重写,以降低接口实现类对接口实现过程难度graph LR; Servt实现类 --extends---> HttpServlet抽象类 --extends---> GenericServlet抽象类 --extends---> Servlet接口
-
定义了一个接口,就是定义了一个可以引用的类型,像类一样,在任何需要的地方作为类型使用
-
接口不能直接实例化,但是可以通过向上转型将其实现类实例化。
抽象类
抽象类是含有一个或多个抽象方法的类。
-
抽象类里可以有抽象方法也可以有普通方法
-
抽象类中可以有构造器,但是不能创造实例对象
-
抽象类的子类都必须重写父类中全部的抽象方法,而不必需重写其普通方法
-
抽象方法
abstract
不能与哪些关键字共存private
:private
修饰的方法只能在本类中使用,而抽象方法要求必须让子类实现,两者相互矛盾
final
:final
修饰的方法不能被重写,而抽象方法必须要被重写,
static
:static
修饰的方法可以通过类名直接调用,而抽象方法是没有方法体的
匿名内部类
匿名内部类,没有名字、不被复用的内部类,通常用来简化代码编写。能够同时的一步到位的,声明和创建一个实现/继承的接口/抽象类的实现类和对象。
1 |
|
函数式编程
Lambda函数
匿名函数组成
简写的函数
匿名函数特点
- 匿名。省略修饰符/返回类型/名称。
- 函数。不属于任何类,有函数体/(参数列表/返回值)。
- 传递。匿名函数可作为参数传递给方法,或作为变量的值
方法引用
双冒号(::
)操作符是 Java 中的方法引用。 使用一个方法的引用时,目标引用放在 ::
之前,目标引用提供的方法名称放在 ::
之后,即 目标引用(类)::方法(类中的方法)
。
1 |
|
函数式接口
函数式接口,能且只能包含1个抽象方法的接口。用@FunctionalInterface
注解标记(可以省略)。
可以使用Lambda表达式创建一个函数式接口的对象,此对象可以用于传参/赋值,如 Stream/Optional 中的一些方法以函数为参数都是基于函数式接口实现的。
1 |
|
集合
集合是存储元素对象的容器。
集合框架
集合框架,用于表示和操作集合的体系结构,包含
- 接口(Interfaces):表示集合的抽象数据类型
- 实现(Implementations):集合接口的具体实现类,由不同的数据结构实现
- 算法(Algorithms):对集合执行搜索/排序等操作
即,Java提供了一套包含,多种集合类型,多种数据结构实现,以及操作处理算法的集合框架,供开发人员直接使用
LIST
graph LR;
0[java.util.List/接口] --基本实现类--- java.util.ArrayList/类
0 --基本实现类--- java.util.LinkedList/类
接口/类 | 特点 | 方法 |
---|---|---|
java.util.List |
有序,允许重复元素 集合类型常量不可改变集合结构,如增/删集合元素将引发异常;可以替换元素,元素对象属性值可以改变 集合为逻辑上的容器,容器中仅保存元素对象的引用地址;操作集合中的元素时,实际操作的是元素引用的对象 |
of() :静态方法,返回空列表对象of(elements…) :静态方法,基于指定元素创建集合对象add(int index, E element) : 将元素插入到指定索引处set(int index, E element) :将指定索引处元素替换get(int index) :获取指定索引处元素getName() : 获取元素名remove(int index) : 移除指定索引处元素toArray(T[] a) :列表转换为数组。创建0长度数组实例即可,方法内部仅将自动调整 |
java.util.ArrayList |
基于对象数组数据结构的实现 | |
java.util.LinkedList |
基于双向链表数据结构的实现 | 为每个元素创建2个节点,保存前/后元素的地址 |
声明与创建
SET
Set集合,不包含重复元素
graph LR;
0[java.util.Map/接口] --基本实现类--- java.util.HashSet/类;
0 --基本实现类--- java.util.LinkedHashSet/类;
0 --基本实现类--- java.util.TreeSet/类
接口/类 | 特点 | 方法 |
---|---|---|
java.util.Set |
不包含重复元素,可实现迭代器 添加重复元素不改变集合也不报错 均无基于索引的操作方法 |
Set.of() 返回空集合对象/集合不可变 Set.of(elements…) 基于指定元素创建集合对象 add(E element)) |
java.util.HashSet |
元素无序 | getName() 无序获取 |
java.util.LinkedHashSet |
元素有序 | |
java.util.TreeSet |
元素有序 |
ITERATOR
Iterator接口,迭代器,帮助集合完成遍历与移除,通过移动游标进行操作。
方法 | 作用 |
---|---|
获取集合对象的迭代器 | |
next() |
向后移动游标后,返回游标指向的元素 |
hasNext() |
Iterator中是否有下一个元素 |
remove() |
从集合移除当前游标指向的元素 |
示例
MAP
Map不是集合;不继承于Iterable接口,不支持forEach遍历;不支持基于索引的操作
graph LR;
0[java.util.Map/接口] --基本实现类--- java.util.HashMap/类
0 --基本实现类--- java.util.TreeMap/类
方法 | 作用 |
---|---|
声明与创建,key必须是唯一的,且每个key只能对应一个value。添加key-value时,如果key已经存在,则后一个覆盖前一个 | |
put(K key, V value) |
保存键值对 |
get(K key) |
基于key获取对应的value,如果value不存在,返回null |
of(K,V,K,V...) |
静态方法,基于指定元素创建键值对对象 |
泛型
泛型,即**“参数化类型”**,是以类或接口为参数的类型参数,用<>
声明,只接受引用类型,不接受基本类型。
泛型类与泛型方法
泛型类
1 |
|
泛型方法
1 |
|
继承和子类型
graph LR;
0[子类型关系] --- 子类关系;
0 --- 元素间拥有继承关系的数组
赋值支持子类型关系,即等号右侧必须是左侧的子类型。
1 |
|
通配符
1 |
|
通配符/标记符(常用于标记泛型形参) | 释义 |
---|---|
E | Element (在集合中使用,因为集合中存放的是元素) |
T | Type(类) |
K | Key(键) |
V | Value(值) |
N | Number(数值类型) |
? | 不确定类型 不能保证参数一致性,通常用于泛型方法的调用代码和形参,不能用于定义类和泛型方法。 |
集合流
集合流不是存储元素的数据结构,而是操作集合元素的管道。仅会对集合中的元素进行操作,不影响源集合结构。
STREAM
方法 | 作用 | 操作类型 |
---|---|---|
获取集合对象的集合流 | Initial Operations 初始化操作 |
|
collect() |
聚合操作结果 | Terminal Operations 终止操作 |
forEach() |
迭代集合流的每个元素 | Terminal Operations 终止操作 |
filter() |
基于参数选择集合流中的元素,过滤 参数表达式结果必须为布尔值,为真置于新集合流,为假过滤掉 |
Intermediate Operations 中间操作 |
map() |
基于条件将集合流中的元素映射为新类型元素,映射 | Intermediate Operations 中间操作 |
sorted() |
排序集合流中的元素,排序 | Intermediate Operations 中间操作 |
count() |
获取集合流中元素个数,计数 | Intermediate Operations 中间操作 |
findFirst() |
从流中取第一个符合条件元素,封装到Optional |
|
java.lang.Comparator Comparator类 |
比较器comparing() ,基于参数表达式排序reversed() ,倒序 |
结合sorted() |
java.util.stream.Collectors Collectors类 |
用于操作聚合结果的工具类toList()/toSet() ,转换聚合结果为指定数据引用类型groupingBy() ,按传入的表达式参数以MAP 形式分组toMap(K,V) ,基于给定键值以MAP 形式分组 |
结合collect() |
OPTIONAL
java.util.Optional<T>
,为解决空引用异常引入的,用于封装单值元素的容器(single-value container)。
方法 | 作用 | 操作类型 |
---|---|---|
Optional<T> Optional.of(T value) |
基于必不为空对象,创建optional容器,注入为空元素将抛出NullPointerException异常 | Initial Operations 初始化操作 |
Optional<T> Optional.ofNullable(T value) |
基于可能为空的对象,创建optional容器 | Initial Operations 初始化操作 |
ifPresent(action) |
当optional容器不为空时,执行指定函数;为空忽略执行仅检测指定元素对象,但嵌套对象为空时依然异常 | Intermediate Operations 中间操作 |
ifPresentOrElse(action, emptyAction) |
当容器不为空时执行第一个函数;为空执行第二个函数 | Intermediate Operations 中间操作 |
.filter() .map() |
与Stream中一致 | Intermediate Operations 中间操作 |
.orElse() |
如果Optional 实例有值则将其返回,否则返回orElse 方法传入的参数 |
Terminal Operations 终止操作 |
操作链
中间操作执行后,将结果置入一个新集合流,从而允许基于新集合流实现后续操作,形成集合流的操作链。
1 |
|
异常
异常,是发生在程序执行过程中的,扰乱了程序正常流程的事件。当方法执行中发生错误时,该方法创建一个对象并将其传递给运行时系统(runtime system)
,该对象称为异常对象(exception object)
。创建一个异常对象,并将其交给运行时系统,称为抛出异常(throwing an exception)
。
异常类型
相关类
java.lang.Throwable类
方法:
String getMessage()
:返回异常信息字符串printStackTrace()
:打印异常栈信息
类型
graph LR;
0[错误/异常类型] --- 1[受检异常Checked Exceptions];
1 -.- 1.1[程序与程序控制之外的外部资源互交时产生的错误];
1 -.- 1.2[如文件无法读取/数据库无法访问/网络无法连接等]
0 --- 2[非受检异常Unchecked Exceptions];
2 -.- 2.1[程序中的错误逻辑/代码];
2 -.- 2.2[如空指针异常/数组集合索引越界等];
0 --- 3[程序错误Error];
3 -.- 3.1[程序外部在特殊条件下产生];
3 -.- 3.2[如系统内存溢出/磁盘损坏]
异常处理
异常处理流程
-
调用栈(Call Stack)
:开始于主函数,终止于发生错误的方法的方法列表 -
异常处理程序(exception handler)
:处理异常的代码块。在调用栈中反序检索得到 (如catch{}
) -
捕获异常(catch the exception)
:系统在调用栈中找到适当的异常处理程序 (若未找到程序终止)
显示处理
可能抛出**受检异常(CheckedException)**的方法,必须显式捕获/抛出异常,否则无法编译。
非受检异常(UncheckedException)无需显式捕获处理,将终止程序,直接抛出异常并打印异常栈信息。
-
try catch
显示捕获处理异常每个catch块都是一个异常处理程序,负责处理指定的异常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41// try-catch 模块
try {
// 可能抛出受检异常的代码块
} catch (ExceptionType name | ExceptionType name) {
// 出现异常类型1执行的操作
} catch (ExceptionType name) {
// 出现异常类型2执行的操作
}
// 示例
try {
Files.readString(Path.of(path))
} catch (IOException e) {
System.out.println(e.getMessage()); // 返回异常信息字符串
e.printTraceStack; // 打印异常栈信息
}
// finally 模块
/* 无异常时,执行try块代码 -> 执行finally块代码 -> try内return语句 / 继续执行块外代码
引发异常时,从try块异常处 -> catch块代码 -> 执行finally块代码 -> catch内return语句 /继续执行块外代码
finally块可用于避免由于方法返回、方法执行异常而意外绕过关闭资源对象代码
仅用于释放资源,禁止参与业务逻辑的处理,块内禁止使用return语句 */
public static String getTryCatchFinally() {
try {
// 可能抛出受检异常的代码块
System.out.println("try块内异常前");
Files.readString(Path.of(path);
System.out.println("try块内异常后");
return "try中结果”;
} catch (IOException e) {
// 出现异常类型执行的操作,不出现异常将被忽略
System.out.println ("catch块内");
} finally {
//不出现异常,在执行return前,程序将跳转finally模块执行,无return语句时将顺序执行之后的代码
System.out.println("finally块内”);
}
System.out.println("finally块后”);
return "finally后结果”;
} -
throws/throw
抛出异常可以在 构造函数/静态方法/实例方法/方法内的代码块/Lambda表达式 等中声明抛出异常
throws
子句,使当前方法抛出异常,交由调用者处理异常。throw
声明,抛出一个异常类的异常实例,跳出当前流程使用
throw
抛出受检/自定义异常E,则其所在的函数必须使用throws
关键字抛出E或E的父类异常。构造函数/静态/实例方法/方法内的代码块/Lambda表达式等中可声明抛出异常。其中抽象方法抛出异常时。重写抽象方法的实例方法才可抛出异常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46// throws子句 ; throw声明
methodname throws Exception1,Exception2,..,ExceptionN { }
// 示例1
public static void getThrows() throws IOException{
Files.readString(Path.of(path);
}
public static void main(String[] args) {
try {
getThrows();
} catch(IOException e) {
System.out.println(e.getMessage());
}
}
// 结合自定义异常
// 自定义异常:通过继承相关异常类实现
/* 继承RuntimeException异常类
实现自定义非受检异常
调用RuntimeException构造函数
实现对自定义异常的相关操作 */
public class MyException extends RuntimeException{
public MyException (String message) {
super(message);
}
public MyException (String message, Throwable cause) {
super(message,cause);
}
}
// 示例2: 检测异常转非检测异常
public static String shiftException() {
try {
Files.readString(Path.of(path);
} catch (IOException e) {
throw new MyException("文件读取错误", e)
}
}
// 示例3:
private static double divide(double divisor, double dividend) {
if (dividend == 0) {
throw new MyException("被除数为空");
return divisor / dividend;
}
多线程
进程 (Processes): 操作系统进行资源分配的最小单元,应用程序的执行实例。
线程 (Threads): 进程中的运行实体,操作系统调度的最小任务单位。当程序中所有线程终止,进程随之终止。
线程的创建
-
实现
Runnable
接口,创建Thread
实例,以Runnable
实现类实例为构造函数参数实现线程和任务解耦
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29// 定义一个实现Runnable接口的任务类
public class HelloRunnable implements Runnable {
private String name;
public HelloRunnable(String name) {
this.name = name;
}
// 根据该线程待执行任务实现run()方法
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + "线程运行: " + i);
try {
Thread.sleep((int Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static void getHelloRunnable() {
// 将Runnable对象基于构造函数传递给Thread对象
Thread hr1=new Thread(new HelloRunnable("ThreadA"));
Thread hr2=new Thread(new HelloRunnable("ThreadB"));
hr1.start();
hr2.start();
} -
继承
Thread
类,重写run()
方法线程和任务未解耦
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// 继承Thread类
public class HelloThread extends Thread {
private String name;
public HelloThread(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + "线程运行: " + i);
try {
sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static void getHelloThread() {
// 创建继承Thread类的类的对象
HelloThread ht1=new HelloThread("ThreadA");
HelloThread ht2=new HelloThread("ThreadB");
ht1.start();
ht2.start();
}
java.lang.Runnable接口
作用:定义预执行的任务
方法:
run()
: 唯一的抽象方法,需要实现类重写方法时在方法中实现需要线程执行的任务
线程的状态
java.lang.Thread类
作用:定义预执行的线程
方法:
-
run()
:实现Runnable
接口,但重写方法为空,需要继承类时再重写方法,在方法中实现需要线程执行的任务执行完毕后,自动停止线程 -
start()
:启动线程 -
sleep()
:静态方法,挂起当前线程,使线程进入非可执行状态,可以通过中断(Interrupt)
来终止 -
interrupt()
:设置中断标识,使指定线程中断,抛出InterruptedException
异常 (抛出异常后中断标识清除) -
boolean interrupted()
:静态方法,检查当前线程是否中断,返回boolean
值,清除中断状态 -
join()
:当前线程暂停执行,直到指定线程终止,可以通过中断(Interrupt)
来终止
java.util.concurrent.CountDownLatch类
作用:允许多个线程等待的同步工具
方法:
countDown()
:减少锁计数器的计数,计数达到零则释放所有等待线程await()
:当前线程暂停执行直到锁计数器递减到
线程同步
synchronized关键字
作用对象:
-
可以作用于类、方法 (包括静态方法)、代码块
-
不得作用于抽象方法、构造函数
作用:修饰部分仅允许一个线程独占访问资源
volatile关键字
作用对象:变量
作用:保证变量的可见性,即各线程不在本地缓存变量副本,每次使用即时从主内存加载变量
java.util.concurrent.locks.Lock接口
作用:控制多线程访问共享资源的工具,提供比同步操作更广泛、更灵活的锁定操作,提供对共享资源的独占访问权限 (一次只有一个线 程可以获取该锁)
方法:
lock()
:锁定任意代码区域try代码块
unlock()
:操作结束后释放锁finally代码块
实现类:ReentrantLock(重入锁)/ReadLock/WriteLock
java.util.concurrent.ExecutorService接口
作用:继承于Executor
,提供了基于指定线程池策略,创建Executor
对象的工厂方法
方法:
-
newSingleThreadExecutor()
:创建只有1个工作线程的线程池,串行执行提交的任务 -
newFixedThreadPool(int nThreads)
:创建固定大小的线程池,每提交一个任务创建一个线程,直到达到指定数量 -
execute(Runnable r)
:添加执行任务到Executor线程池
-
shutdown()
:禁止添加新任务,等待当前执行中以及任务队列中的所有任务执行完成,关闭线程池 -
List<Runnable> shutdownNow()
:取消任务队列中需执行的任务,返回未执行任务列表。通过向线程池线程发送interrupt
中断信号,由其中执行的任务捕获处理异常。执行中的任务结束后关闭线程池。
java.util.concurrent.atomic包
作用:实现对特定变量类型的单个变量进行原子操作
包含类:如标量类:AtomicBoolean,AtomicInteger;数组类:AtomicIntegerArray等
方法:get()/set()/increment()
:类似在volatile
变量上读写
java.lang.ThreadLocal<T>类
作用:提供线程局部变量,如充当web容器,持有每个请求线程的变量副本
IO流
I/O
IO流,数据源/数据目标、输入/输出的抽象表示
文件的数据形式
数据文件是基于byte(字节)
而非bit(位)
保存以及传输
1个byte(字节)
== 8个二进制bit(位)
== 1个255以内的十进制整数
1个char(字符)
占的字节与编码有关。英文字符占1个字节;中文字符,在UTF8(Windows 10)
中占3个字节,在GBK (Windows 7)
中占2个字节
java.io.InputStream抽象类
输入流
实现子类:FileInputStream,ByteArrayInputStream等
方法:
-
构造函数:抛出
IOException
-
int read() throws IOException
:抽象方法,由具体子类实现。基于单字节操作,返回流中下一字节的十进制整数形式;到达流末无可读字节,返回-1int read(byte[] b)
:字节数组缓冲区,将流中字节读取到字节数组中,第1个字节置入数组[0]…,直到读取到数组长度的字节位置为止;返回读取的字节长度;如果没有可读字节,返回-1 -
close() throws IOException
:关闭资源 -
long transferTo(out) throws IOExecption
:直接将输入流中字节转移至输出流,返回总字节长度 -
byte[] readAllBytes() throws IOException
:将输入流中所有字节读出到字节数组
java.io.OutputStream抽象类
输出流
实现子类同输入流
方法
-
构造函数:抛出
IOException
-
void write(int b) throws IOException
:抽象方法,基于单字节操作,将十进制整数按字节写入输出 -
void write(byte[] b, int off, int len)
,从字节数组[off]开始读取,至数组[len]结束 -
close() throws IOException
:关闭资源
自动关闭
完整IO代码
1 |
|
java.lang.AutoCloseable接口
任何实现了java.lang.AutoCloseable接口的类型,均是支持自动关闭的资源类型,java.io.Closeable接口继承AutoCloseable接口
try-with-resources语句
在try()
语句中声明需要被关闭的资源,资源将在try{}
结束后自动关闭,如:
1 |
|
文件系统
NIO2 (java8) 将文件路径与文件操作分离,支持异步非阻塞
java.nio.file.Path接口
作用:不依赖于系统的描述文件路径 (即运行在不同操作系统下具体实现不同)
方法
-
创建:
-
java.nio.file.Paths类
1
Path p = Paths.get("/tmp/foo");
-
Path.of()静态方法
1
Path p = Path.of("/tmp/foo");
-
-
获取:
1
// 如 对于路径"D:/test/input.txt"
-
Path getFileName()
:返回文件名或名称元素序列的最后一个元素"input.txt"
-
Path getParent()
:返回父目录的路径D:\test
-
Path getRoot()
:返回路径的根D:\
-
-
拼接:
-
Path resolve(Path other)
:拼接各级路径1
2
3Path dir = Path.of("D:/test");
Path file = Path.of("input.txt");
Path p = dir.resolve(file);
-
java.nio.file.Files类
作用:通过丰富的静态方法,读取/写入/操作文件与目录
方法(以下方法均为静态方法):
-
检查
boolean exists(Path path) / notExists(Path path)
:检查路径是否存在boolean isDirectory(Path path)
:检查是否为目录
-
创建
-
Path createDirectory(Path dir) throws IOException
:创建单级目录,目录路径为多级或已存在则异常 -
Path createDirectories(Path dir) throws IOException
:创建多级目录 -
Path createFile(path) throws IOException
:基于指定路径创建文件,文件已存在则异常1
2
3
4
5private static void createFile throws IOException {
Path file = Path.of("D:/test/input.txt");
Files.createDirectories(file.getParent());
Files.createFile(file);
}
-
-
复制
-
Path copy(Path source, Path target, CopyOption... options) throws IOException
:将文件复制到目标文件,默认如果文件已经存在则异常java.nio.file.StandardCopyOption枚举
:实现了CopyOption接口
,提供复制选项CopyOption
ATOMIC_MOVE
:将文件作为原子文件操作移动 (多线程操作)COPY_ATTRIBUTES
:将属性复制到新文件REPLACE_TXISTING
:如果文件已存在则替换现有文件
1
2
3
4
5
6private static void createFile throws IOException {
Path dir = Path.of("D:/test");
Path source = dir.resolve("input.txt");
Path target = dir.resolve("output.txt");
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
}
-
-
移动
Path move(Path source, Path target, CopyOption... options) throws IOException
:将文件移动或重命名 (相同目录下) 为目标文件,默认目标文件存在则异常
-
删除
delete(Path path) throws IOException
:基于指定路径删除文件/目录,路径不存在/删除目录不为空则异常boolean deleteIfExists(Path path) throws IOException
:路径不存在时不删除,返回是否删除成功,删除目录不为空则异常
-
遍历
参考资料
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!