建议先阅读 JavaSE基础篇
静态成员变量(有static修饰,属于类,内存中加载一次):常表示如在线人数信息、等需要被共享的信息,可以被共享访问。
格式:类名.变量名
对象.变量名(不推荐)
实例成员变量(无static修饰,存在于每个对象中):常表示姓名name、年龄age、等属于每个对象的信息。
格式:类名.变量名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X5ieQfpX-1684550850442)(.\img\static修饰成员变量的内存原理.png)]
使用场景:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dh6tkz6F-1684550850443)(.\img\static修饰成员方法的内存原理.png)]
在用类获取对象的时候,对象已经提前为你准备好了
设计步骤:
提高代码复用性,减少代码冗余,增强类的功能扩展性。
在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。
应用场景:
子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己。
为什么?
怎么调用父类构造器的?
子类构造器的第一行语句默认都是:super() 不写也存在。
初始化继承自父类的数据。
如果父类中没有无参数构造器,只有有参构造器,会报错。因为子类默认是调用父类无参构造器的。
子类构造器中可以通过书写super(…),手动调用父类的有参数构造器
this(…)和super(…)使用注意点:
子类通过this(…)去调用本类的其他构造器,本类其他构造器会通过super(…)去手动调用父类的构造器,最终还是会调用父类构造器的。
注意:this(…)和super(…)都只能放在构造器的第一行,所以二者不能共存在同一个构造器中。
修饰符 enum 枚举名称{
第一行是罗列枚举类实例的名称
}
enum Season{
SPRING , SUMMER , AUTUMN , WINTER
}
使用场景说明:
当系统中出现同一个功能多处在开发,而该功能中大部分代码是一样的,只有其中部分可能不同的时候
模板方法模式实现步骤
把功能定义成一个所谓的模板方法,放在抽象类中,模板方法中只定义通用且能确定的代码
模板方法中不能决定的功能定义成抽象方法让子类去实现
模板方法建议用final修饰,防止子类重写,是直接给子类使用的,不让子类重写。一旦重写,模板方法就失效了。
接口的格式
//接口用关键字interface来定义
public interface 接口名{
//常量
//抽象方法
}
JDK8之前接口中只能是抽象方法和常量,没有其他成分了
接口是用来被类实现(implements)的,实现接口的类称为实现类。实现类可以理解成所谓的子类
修饰符 class 实现类 implements 接口1,接口2,接口3...{
}
//实现的关键字implements
从上面可以看出,接口可以被类实现,也可以被类多实现
JDK8版本之后,Java只对接口的成员方法进行了新增,允许接口中直接定义带有方法体的代码
JDK8新增的3种方法我们自己在开发中很少使用,通常是
Java源码涉及到。现阶段需要理解、识别语法,明白调用关
系即可。
同类型的对象,执行同一个行为,会表现出不同的行为特征。
多态的常见形式
父类类型 对象名称 = new 子类构造器
接口 对象名称 = new 实现类构造器
多态中成员访问特点
多态的前提
自动类型转换(从子到父):
子类对象赋值给父类类型的变量指向
强制类型转换(从父到子)
内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)
public class People{
//内部类
public class Heart{
}
}
静态内部类
什么是静态内部类
有static修饰,属于外部类本身
它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已
public class Outer{
//静态成员内部类
public static class Inner{
}
}
静态内部类创建对象的格式
格式:外部类名.内部类名 对象名 = new 外部类名.内部类构造器;
静态内部类的访问拓展
成员内部类
什么是成员内部类
无static修饰,属于外部类的对象
JDK16之前,成员内部类中不能定义静态成员,JDK16开始也可以定义静态成员了
public class Outer{
//成员内部类
public class Inner{
}
}
内部类创建对象的格式
格式:外部类名.内部类名 对象名 = new 外部类构造器.new内部类构造器;
成员内部类中可以直接访问外部类的静态成员,外部类的静态成员只有一份可以被共享访问
成员内部类中可以直接访问外部类的实例成员。因为必须先有外部类对象,才能有成员内部类对象。
注意:在成员内部类中访问所在外部类对象,格式:外部类名.this
局部内部类(鸡肋)
匿名内部类(重点)
本质上是一个没有名字的局部内部类,定义在方法中、代码块中、等。
作用:方便创建子类对象,最终目的为了简化代码。
格式:
new 类|抽象类名|接口名(){
重写方法;
}
Employee a = new Employee(){
public void work(){
}
}
特点:
匿名内部类在开发中的使用形式
方法名 | 说明 |
---|---|
public Sting toString() | 默认返回当前对象在堆内存中的地址信息:类的全限名@内存地址 |
public Boolean equals(Object o) | 默认是比较当前对象与另一个对象的地址是否相同,相同放回true,不同返回false |
toString方法
equals方法
方法名 | 说明 |
---|---|
public static boolean equals(Object a, Object b) | 比较两个对象的,底层会先进行非空判断,从而可以避免空指针异常,再进行equals比较 |
public static boolean isNull(Object obj) | 判断变量是否为null,为null返回true否则返回false |
Objects概述
构造器名称 | 说明 |
---|---|
public StringBuilder() | 创建一个空白的可变的字符串对象,不包含任何内容 |
public StringBuilder(String str) | 创建一个指定字符串内容的可变字符串对象 |
常用方法
方法名称 | 说明 |
---|---|
public String Builder append(任意类型) | 添加数据并返回StringBuilder对象本身 |
public StringBuilder reverse() | 将对象的内容反转 |
public int length() | 返回对象内容长度 |
public String toString() | 通过toString()就可以实现把StringBuilder转换为String |
StringBuilder概述
常用方法
方法名 | 说明 |
---|---|
public static int abs(int a) | 获取参数绝对值 |
public static double ceil(double a) | 向上取整 |
public static double floor(double a) | 向下取整 |
public static int round(float a) | 四舍五入 |
public static int max(int a, int b) | 获取两个int中的较大值 |
public static double pow(double a,double b) | 返回a的b次方 |
public static double random() | 返回值为double的随机数,范围[0.0,1.0) |
概述
常用方法
方法名 | 说明 |
---|---|
public static void exit(int status) | 终止当前运行的Java虚拟机,非0表示异常终止 |
public static long currentTimeMillis() | 返回当前系统的时间毫秒值类型 |
public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数) | 数组拷贝 |
时间毫秒值
作用
使用步骤
创建对象BigDecimal封装浮点型数据(最好的方式是调用方法)
public static BigDecimal valueOf(double val)
//包装浮点数成为BigDecimal对象
常用API
方法名 | 说明 |
---|---|
public BigDecimal add(GigDecimal b) | 加法 |
public BigDecimal subtract(GigDecimal b) | 减法 |
public BigDecimal multiply(GigDecimal b) | 乘法 |
public BigDecimal divide(GigDecimal b) | 除法 |
public BigDecimal divide(另一个BigDecimaly对象,精确几位,舍入模式) | 除法 |
**注意:**BigDecimal只做精度运算,如果给的值不能精度运算,就会报错.可以使用参数来限制精确位数
概述:
构造器:
名称 | 说明 |
---|---|
public Date() | 创建一个Data对象,代表的是系统当前此刻日期时间 |
public Date(long time) | 把时间毫秒值转换成Date日期对象(年月日形式) |
常用方法:
名称 | 说明 |
---|---|
public long getTime() | 获取时间对象的毫秒值 |
public void setTime(long time) | 设置日期对象的时间为当期时间毫秒值对应的时间 |
Date类记录时间的2种形式
作用:
构造器:
构造器 | 方法 |
---|---|
public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认格式 |
public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat使用指定格式 |
常用方法:
名称 | 说明 |
---|---|
public final String format(Date date) | 将日期格式转化成日期/时间字符串 |
public final String format(Object date) | 将时间毫秒值转化成日期/时间字符串 |
public Date parse(String source) | 从给定字符串的开始解析文本以生成日期 |
格式化的时间形式的常用的模式对应关系如下:
y—— 年,M——月,d——日,H——时,m——分,s——秒,E——星期,a——上午/下午
例如:
2020-11-1113:27:06——yyyy-MM-dd HH:mm:ss
2020年11月11日13:27:06——
yyyy年MM月dd日HH:mm:ss
注意:使用parse时输入的字符串格式和创建对象的时候的格式必须相同
概述:
创建对象的方法:
方法名 | 说明 |
---|---|
public static Calendar getInstance() | 获取当前日历对象 |
常用方法:
方法名 | 说明 |
---|---|
public int get(int field) | 取日期中的某个字段信息 |
public void set(int field,int value) | 修改日历的某个字段信息 |
public void add(int field,int amount) | 为某个字段增加或减少指定的值 |
public final Date getTimr() | 拿到此刻日期对象 |
public long getTimeInMillis() | 拿到此刻时间毫秒值 |
注意:日历是可变日期对象,一旦修改后其对象本身表示的时间将产生变化
创建对象
方法名 | 说明 | |
---|---|---|
public static Xxxx now(); | 静态方法,根据当前时间创建对象 | LocaDate localDate = LocalDate.now();LocalTime llocalTime = LocalTime.now();LocalDateTime localDateTime = LocalDateTime.now(); |
public static Xxxx of(…); | 静态方法,指定日期/时间创建对象 | LocalDate localDate1 = LocalDate.of(2099 , 11,11);LocalTime localTime1 = LocalTime.of(11, 11, 11);LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43); |
LocalDate、LocalTime、LocalDateTime获取信息的API
方法名 | 说明 |
---|---|
public int geYear() | 获取年 |
public int getMonthValue() | 获取月份(1-12) |
Public int getDayOfMonth() | 获取月中第几天乘法 |
Public int getDayOfYear() | 获取年中第几天 |
Public DayOfWeek getDayOfWeek() | 获取星期 |
LocalDateTime的转换API
方法名 | 说明 |
---|---|
public LocalDate toLocalDate() | 转换成一个LocalDate对象 |
public LocalTime toLocalTime() | 转换成一个LocalTime对象 |
修改相关API
方法名 | 说明 |
---|---|
plusDays, plusWeeks, plusMonths, plusYears | 向当前 LocalDate 对象添加几天、 几周、几个月、几年 |
minusDays, minusWeeks, minusMonths, minusYears | 从当前 LocalDate 对象减去几天、 几周、几个月、几年 |
withDayOfMonth, withDayOfYear, withMonth, withYear | 将月份天数、年份天数、月份、年 份 修 改 为 指 定 的 值 并 返 回 新 的 LocalDate 对象 |
isBefore, isAfter | 比较两个 LocalDate |
instant时间戳
Instant instant = Instant.now();
System.out.println("当前时间戳是:" + instant);
Date date = Date.from(instant);
System.out.println("当前时间戳是:" + date);
instant = date.toInstant();
System.out.println(instant);
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//2021-03-01T15:09:17.444190900
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String ldtStr = ldt.format(dtf);
System.out.println(ldtStr);//2021-03-01 15:09:17
String ldtStr1 = dtf.format(ldt);
System.out.println(ldtStr1);//2021-03-01 15:09:17
LocalDate today = LocalDate.now();
System.out.println(today); // 2021-03-01
LocalDate birthDate = LocalDate.of(1995, 1, 11);
System.out.println(birthDate); // 1995-01-11
Period period = Period.between(birthDate, today);
System.out.printf("年龄 : %d 年 %d 月 %d 日", period.getYears(), period.getMonths(), period.getDays());
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
LocalDateTime birthDate = LocalDateTime.of(1990,10,1,10,50,30);
System.out.println(birthDate);
Duration duration = Duration.between(birthDate, today);//第二个参数减第一个参数System.out.println(duration.toDays());//两个时间差的天数System.out.println(duration.toHours());//两个时间差的小时数System.out.println(duration.toMinutes());//两个时间差的分钟数System.out.println(duration.toMillis());//两个时间差的毫秒数System.out.println(duration.toNanos());//两个时间差的纳秒数
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
LocalDateTime birthDate = LocalDateTime.of(1990,10,1,10,50,30);
System.out.println(birthDate);
System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today));
System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today));
System.out.println("相差的周数:" + ChronoUnit.WEEKS.between(birthDate, today));
System.out.println("相差的天数:" + ChronoUnit.DAYS.between(birthDate, today));
System.out.println("相差的时数:" + ChronoUnit.HOURS.between(birthDate, today));
System.out.println("相差的分数:" + ChronoUnit.MINUTES.between(birthDate, today));
System.out.println("相差的秒数:" + ChronoUnit.SECONDS.between(birthDate, today));
System.out.println("相差的毫秒数:" + ChronoUnit.MILLIS.between(birthDate, today));
System.out.println("相差的微秒数:" + ChronoUnit.MICROS.between(birthDate, today));
System.out.println("相差的纳秒数:" + ChronoUnit.NANOS.between(birthDate, today));
System.out.println("相差的半天数:" + ChronoUnit.HALF_DAYS.between(birthDate, today));
System.out.println("相差的十年数:" + ChronoUnit.DECADES.between(birthDate, today));
System.out.println("相差的世纪(百年)数:" + ChronoUnit.CENTURIES.between(birthDate, today));
System.out.println("相差的千年数:" + ChronoUnit.MILLENNIA.between(birthDate, today));
System.out.println("相差的纪元数:" + ChronoUnit.ERAS.between(birthDate, today));
基本数据类型 | 引用数据类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
**自动装箱:**基本类型数据和变量可以直接赋值给包装类型的变量
**自动拆箱:**包装类型的变量可以直接赋值给基本数据类型的变量
字符串对象提供了匹配正则表达式规则的API
public 博哦了按matches(String regex)//判断是否匹配正则表达式,匹配返回true,不匹配返回false
字符类(默认匹配一个字符)
[abc] 只能是a, b, 或c
[^abc] 除了a, b, c之外的任何字符
[a-zA-Z] a到z A到Z,包括(范围)
[a-d[m-p]] a到d,或m通过p:([a-dm-p]联合)
[a-z&&[def]] d, e, 或f(交集)
[a-z&&[^bc]] a到z,除了b和c:([ad-z]减法)
预定义的字符类(默认匹配一个字符)
. 任何字符
\d 一个数字: [0-9]
\D 非数字: [^0-9]
\s 一个空白字符: [ \t\n\x0B\f\r]
\S 非空白字符: [^\s]
\w [a-zA-Z_0-9] 英文、数字、下划线
\W [^\w] 一个非单词字符
贪婪的量词
X? X , 一次或根本不
X* X,零次或多次
X+ X , 一次或多次
X {n} X,正好n次
X {n, } X,至少n次
X {n,m} X,至少n但不超过m次
方法名 | 说明 |
---|---|
public String replaceAll(String regex,String newStr) | 按照正则表达式匹配的内容进行替换 |
public String[] split(String regex): | 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。 |
方法名 | 说明 |
---|---|
public static String toString(类型[] a) | 返回数组的内容(字符串形式) |
public static void sort(类型[] a) | 对数组进行默认升序排序 |
public static void sort(类型[] a, Comparator super T> c) | 使用比较器对象自定义排序 |
public static int binarySearch(int[] a, int key) | 二分搜索数组中的数据,存在返回索引,不存在返回-1 |
方法名 | 说明 |
---|---|
public static void sort(类型[] a) | 对数组进行默认升序排序 |
public static void sort(类型[] a, Comparator super T> c) | 使用比较器对象自定义排序 |
自定义排序规则:
如果认为左边数据 大于 右边数据 返回正整
如果认为左边数据 小于 右边数据 返回负整数
如果认为左边数据 等于 右边数据 返回0
选择排序的思想:
选择排序的关键:
package com.zhl.d8_binarysezrch;
import java.util.Arrays;
public class Test1 {
public static void main(String[] args) {
//选择排序
int[] arr = {2,5,3,1,4};
for (int i = 0; i < arr.length-1; i++) {
for (int j = i+1;j < arr.length ; j++){
if (arr[i]>arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
基本查找:
在数据量特别大的时候,基本查找从前往后查找的性能是很差的
二分查找:
package com.zhl.d8_binarysezrch;
public class Test2 {
public static void main(String[] args) {
//二分查找
int[] arr = {1,3,5,7,9,11,13,15,17,19};
// 0,1,2,3,4,5 ,6 ,7 ,8 , 9
System.out.println(binarySearch(arr, 19));
}
/**
* 二分查找法
* @param arr 数组
* @param data 查找数据
* @return 索引/-1(找不到元素)
*/
public static int binarySearch(int[] arr,int data){
int left = 0;
int right = arr.length-1;
while (left<=right){
int midIndex = (left+right)/2;
if (data > arr[midIndex]){
left = midIndex+1;
}else if (data < arr[midIndex]){
right = midIndex-1;
} else {
return midIndex;
}
}
return -1;
}
}
Lambda表达式是JDK8开始后的一种新语法形式
作用:简化函数式接口的匿名内部类的代码写法
格式:
(匿名内部类被重写方法的形参列表) ->{
被重写方法的方法体代码。
}
注:-> 是语法形式,无实际含义
注意:Lambda表达式只能简化函数式接口的匿名内部类的写法形式
什么是函数式接口?
集合是java中存储对象的一种容器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hvhY4zlk-1684550850446)(.\img\集合体系结构.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L6oHpoKy-1684550850447)(.\img\Collection集合体系.png)]
方法名称 | 说明 |
---|---|
public boolean add(E e) | 把给定的对象添加到当前集合中 |
public void clear() | 清空集合中所有的元素 |
public boolean remove(E e) | 把给定的对象在当前集合中删除 |
public boolean contains(Object obj) | 判断当前集合中是否包含给定的对象 |
public boolean isEmpty() | 判断当前集合是否为空 |
public int size() | 返回集合中元素的个数。 |
public Object[] toArray() | 把集合中的元素,存储到数组中 |
概述:
Collection集合获取迭代器
方法名称 | 说明 |
---|---|
Iterator iterator() | 返回集合中的迭代器对象,该迭代器对象默认指向当前集合的0索引 |
常用方法:
方法名称 | 说明 |
---|---|
boolean hasNext() | 询问当前位置是否有元素存在,存在返回true ,不存在返回false |
E next() | 获取当前位置的元素,并同时将迭代器对象移向下一个位置,注意防止取出越界。 |
增强for循环:既可以遍历集合也可以遍历数组
它是JDK5之后出现的,其内部原理是一个Iterator迭代器,遍历集合相当于是迭代器的简化写法
实现Iterable接口的类才可以使用迭代器和增强for,Collection接口已经实现了Iterable接口。
格式
for(元素数据类型 变量名:数组或者Collection集合){
//在此处使用变量即可,该元素就是元素
}
方法名称 | 说明 |
---|---|
default void forEach(Consumer super T> action): | 结合lambda遍历集合 |
数据结构概述
常见的数据结构
栈数据结构的执行特点
队列
数组是一种添加快,增删慢的模型
==查询速度快:==查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)
**删除效率低:**要将原始数据删除,同事后面每个数据前移
**添加效率极低:**添加位置后的每个数据后移,载添加元素
链表中的元素是在内存中不连续存储的,每个元素节点包含数据值和下一个元素地址
**链表查询慢:**无论查找哪个数据都要从头开始找(对比数组)
链表增删相对快(对比数组)
种类
二叉树概念:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V5ipg8Hh-1684550850448)(.\img\二叉树概念.png)]
二叉树特点:
二叉查找树:
二叉查找树又称二叉排序树或者二叉搜索树。
二叉查找树的特点:
二叉查找树存储规则:
二叉查找树存在的问题:
平衡二叉树:
平衡二叉树的要求:
平衡二叉树在添加元素后肯导致不平衡:
平衡二叉树-旋转的四种情况:
左左
当根节点左子树的左子树有节点插入,导致二叉树不平衡
左右
当根节点左子树的右子树有节点插入,导致二叉树不平衡
右右
当根节点右子树的右子树有节点插入,导致二叉树不平衡
右左
当根节点右子树的左子树有节点插入导致二叉树不平衡
红黑树概述:
红黑规则:
添加节点:
红黑树增删改查的性能都很好
list系列集合特点:
List系列特有方法:
List集合因为支持索引,所以多了很多索引操作的独特API,其他Collection的功能List也继承了
方法名称 | 说明 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
List集合的遍历方式:
package com.zhl.d5_collection_list;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Test2 {
public static void main(String[] args) {
List<Integer> list1 = new LinkedList<>();
list1.add(11);
list1.add(22);
list1.add(33);
list1.add(44);
list1.add(66);
System.out.println(list1);
System.out.println("--------------------");
//- 迭代器
Iterator it = list1.iterator();
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println("--------------------");
//- 增强for循环
for (Integer e : list1) {
System.out.println(e);
}
System.out.println("--------------------");
//- Lambda表达式
list1.forEach(e-> System.out.println(e));
System.out.println("--------------------");
//- for循环(因为List集合存在索引)
for (int i = 0; i < list1.size(); i++) {
System.out.println(list1.get(i));
}
}
}
特有API
方法名称 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
问题引出:
哪些遍历方式存在问题:
那种遍历不会出现问题:
泛型的概述:
泛型的好处:
泛型类的概述:
泛型类原理:
泛型方法的概述:
泛型方法原理:
泛型接口的概述:
泛型接口的原理:
通配符:
泛型的上下限:
Set系列集合特点:
Set集合实现类特点:
Set集合的功能上基本与Collection的API一致
HashSet底层原理:
哈希表的组成:
HashSet1.7版本原理解析:数组+链表+(结合哈希算法)
JDK1.8版本开始HashSet原理解析:
从JDK8开始后,哈希表对于红黑树的引入进一步提高了操作数据的性能
如果希望Set集合认为两个内容一样的对象是重复的,必须重写对象的hashCode()和equals()方法
LinkedHashSet集合概述和特点:
TreeSet集合概述和特点:
TreeSet默认排序规则:
如果想要使用TreeSet存储自定义类型,需要制定排序规则
自定义排序规则:
可变参数:
可变参数的作用:
可变参数的注意事项:
Collections集合工具类:
Collections常用API:
方法名称 | 说明 |
---|---|
public static boolean addAll(Collection super T> c, T… elements) | 给集合对象批量添加元素 |
public static void shuffle(List> list) | 打乱List集合元素的顺序 |
public static void sort(List list) | 将集合中元素按照默认规则排序 |
public static void sort(List list,Comparator super T> c) | 将集合中元素按照指定规则排序 |
collections排序相关API:
Map集合概述和使用:
Map集合整体格式:
Map集合体系:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fC7ogyhw-1684550850449)(.\img\Map集合体系.png)]
说明:
Map集合的特点:
Map集合的特点:
Map集合:
常用API:
方法名称 | 说明 |
---|---|
V put(K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
方法名称 | 说明 |
---|---|
Set keySet() | 获取所有键的集合 |
V get(Object key) | 根据键获取值 |
方法名称 | 说明 |
---|---|
Set |
获取所有键值对对象的集合 |
K getKey() | 获得键 |
V getValue() | 获取值 |
方法名称 | 说明 |
---|---|
default void forEach(BiConsumer super K, ? super V> action) | 结合lambda遍历Map集合 |
HashMap的特点:
实际上:Set系列集合的底层就是Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
LinkedHashMap集合概述和特点
TreeMap集合概述和特点:
TreeMap集合自定义排序规则有2种:
Map集合实现类特点:
案例:
l某个班级多名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A、B、C、D),每个学生可以选择多个景点,请统计出最终哪个景点想去的人数最多。
分析
l将80个学生选择的数据拿到程序中去,需要记住每个学生选择的情况。
l定义Map集合用于存储最终统计的结果。
package com.zhl.d12_map_nested;
import java.util.*;
public class Test {
public static void main(String[] args) {
Map<String, List<String>> rs = new LinkedHashMap<>();
String[] attractions = {"A", "B", "C", "D"};
Random r = new Random();
for (int i = 0; i < 80; i++) {
List<String> list= new ArrayList<>();
String name = "学生"+(i+1);
for (int j = 0; j < r.nextInt(attractions.length)+1; j++) {
list.add(attractions[r.nextInt(attractions.length)]);
}
rs.put(name,list);
}
System.out.println(rs);
Map<String,Integer> rsNum = new HashMap<>();
Collection<List<String>> values = rs.values();
for (List<String> value : values) {
for (String s : value) {
if (rsNum.containsKey(s)){
rsNum.put(s, rsNum.get(s)+1);
}else {
rsNum.put(s, 1);
}
}
}
System.out.println(rsNum);
}
}
在List,Set,Map接口中,都存在of方法,可以创建一个不可变集合。
方法名称 | 说明 |
---|---|
static List of(E…elements) | 创建一个具有指定元素的List集合对象 |
static Set of(E…elements) | 创建一个具有指定元素的Set集合对象 |
static |
创建一个具有指定元素的Map集合对象 |
这个集合不能添加,不能删除,不能修改
什么是Stream流:
Stream流的思想:
Stream流的三类方法:
Stream操作集合或者数组的第一步是先得到Stream流,然后才能使用流的功能。
集合获取Stream流的方式
名称 | 说明 |
---|---|
default Stream stream() | 获取当前集合对象的Stream流 |
数组获取Stream流的方式:
名称 | 说明 |
---|---|
public static Stream stream(T[] array) | 获取当前数组的Stream流 |
public static Stream of(T… values) | 获取当前数组/可变数据的Stream流 |
中间操作方法:
名称 | 说明 |
---|---|
Stream filter(Predicate super T> predicate) | 用于对流中的数据进行过滤。 |
Stream limit(long maxSize) | 获取前几个元素 |
Stream skip(long n) | 跳过前几个元素 |
Stream distinct() | 去除流中重复的元素。依赖(hashCode和equals方法) |
static Stream concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
注意:
终结操作方法:
名称 | 说明 |
---|---|
void forEach(Consumer action) | 对此流的每个元素执行遍历操作 |
long count() | 返回此流中的元素数 |
注意:终结操作方法,调用完成后流就无法继续使用了,原因是不会返回Stream了
Stream流的收集:
Stream流的收集方法
名称 | 说明 |
---|---|
R collect(Collector collector) | 开始收集Stream流,指定收集器 |
Collectors工具类提供了具体的收集方式
名称 | 说明 |
---|---|
public static Collector toList() | 把元素收集到List集合中 |
public static Collector toSet() | 把元素收集到Set集合中 |
public static Collector toMap(Function keyMapper , Function valueMapper) | 把元素收集到Map集合中 |
什么是异常:
为什么要学习异常
异常体系:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JTDXPGc9-1684550850449)(.\img\异常体系.png)]
Error:
Exception:
java.lang包下,称为异常类,它表示程序本身可以处理问题
编译时异常和运行时异常:
运行时异常实例:
运行时异常:一般是程序员业务没有考虑好或者是编程逻辑不严谨引起的程序错误,自己的水平有问题!
编译时异常的作用是什么:
编译时异常:继承自Exception的异常或者其子类
是担心程序员的技术不行,在编译阶段就爆出一个错误,目的在于提醒不要出错!
编译时异常时可遇不可求。遇到就遇到了
默认会在出现异常的代码那里自动的创建一个异常对象:ArithmeticException。
异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机。
虚拟机接收到异常对象后,先在控制台直接输出异常栈信息数据。
直接从当前执行的异常点干掉当前程序。
后续代码没有机会执行了,因为程序已经死亡。
编译时异常的处理形式有三种:
异常处理方式1一throws:
throws:用在方法上,可以将方法内部出现的异常抛出去给本方法的调用者处理。
这种方式并不好,发生异常的方法自己不处理异常,如果异常最终抛出去给虚拟机将引起程序死亡。
格式:
方法 throws 异常1,异常2,异常3,..{
}
规范做法:
方法 throws Exception{
}
异常处理方式2一一try…catch
监视捕获异常,用在方法内部,可以将方法内部出现的异常直接捕获处理。
这种方式还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行。
try{
//监视可能出现异常的代码
}eactch(异常类型1 变量){
//处理异常
}eactch(异常类型1 变量){
//处理异常
}...
异常处理方式3一一前两者结合:
运行时异常的处理形式
package com.zhl.d12_exception_handle_test;
import java.util.Random;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// 需求
// 键盘录入一个合理的价格为止(必须是数值,值必须大于0)。
Scanner sc = new Scanner(System.in);
System.out.println("请输入价格:");
while (true){
int price=0;
String s = sc.nextLine();
try {
price = Integer.valueOf(s);
if (price>0){
System.out.println("输入成功"+price);
break;
}else {
System.out.println("必须大于0");
}
} catch (Exception e) {
System.out.println("输入有误,请重新输入");
}
}
}
}
自定义异常的必要:
自定义异常的好处:
可以使用异常的机制管理业务问题,如提醒程序员注意。
自定义异常的分类:
自定义编译时异常
作用:编译时异常是编译阶段就报错,提醒更加强烈,必须要处理
自定义运行时异常
作用:提醒不强烈,编译阶段不报错!!运行时才可能出现!!
弊端:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GwGMK6KW-1684550850450)(.\img\日志体系结构.png)]
步骤:
在项目下新建文件夹lib,导入Logback的相关jar包到该文件夹下,并添加到项目依赖库中去。
将Logback的核心配置文件logback。xml直接拷贝到src目录下
在代码中获取日志对象
public static final Logger LOGGER = LoggerFaction.getLogger("类对象");
Logback日志系统的特新都是通过核心配置文件logback.xml控制的。
Logback日志输出位置、格式设置:
输出到控制台的配置标志
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
输出到系统文件的配置标志
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
日志级别:
具体在
方法名称 | 说明 |
---|---|
public File(String pathname) | 根据文件路径创建文件对象 |
public File(String parent, String child) | 根据父路径名字符串和子路径名字符串创建文件对象 |
public File(File parent, String child) | 根据父路径对应文件对象和子路径名字符串创建文件对象 |
File file1 = new File(“D:\\itheima\\a.txt”);
File file3 = new File(“模块名\\a.txt”);
方法名称 | 说明 |
---|---|
public boolean isDirectory() | 判断此路径名表示的File是否为文件夹 |
public boolean isFile() | 判断此路径名表示的File是否为文件 |
public boolean exists() | 判断此路径名表示的File是否存在 |
public long length() | 返回文件的大小(字节数量) |
public String getAbsolutePath() | 返回文件的绝对路径 |
public String getPath() | 返回定义文件时使用的路径 |
public String getName() | 返回文件的名称,带后缀 |
public long lastModified() | 返回文件的最后修改时间(时间毫秒值) |
方法名称 | 说明 |
---|---|
public boolean createNewFile() | 创建一个新的空的文件 |
public boolean mkdir() | 只能创建一级文件夹 |
public boolean mkdirs() | 可以创建多级文件夹 |
public boolean delete() | 删除由此抽象路径名表示的文件或空文件夹 |
方法名称 | 说明 |
---|---|
public String[] list() | 获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。 |
public File[] listFiles()(常用) | 获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点) |
listFiles方法注意事项:
注意:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pbfOMPK-1684550850450)(.\img\汉字存储和展示过程解析.png)]
方法名称 | 说明 |
---|---|
byte[] getBytes() | 使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
byte[] getBytes(String charsetName) | 使用指定的字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
构造器 | 说明 |
---|---|
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的 String |
String(byte[] bytes, String charsetName) | 通过指定的字符集解码指定的字节数组来构造新的 String |
IO流也称为输入、输出流,就是用来读写数据的。
按流的方向分
按流中的数据最小单位分为
字节流
操作所有类型的文件
字符流
只操作纯文本文件
构造器 | 说明 |
---|---|
public FileInputStream(File file) | 创建字节输入流管道与源文件对象接通 |
public FileInputStream(String pathname) | 创建字节输入流管道与源文件路径接通 |
方法名称 | 说明 |
---|---|
public int read() | 每次读取一个字节返回,如果字节已经没有可读的返回-1 |
public int read(byte[] buffer) | 每次读取一个字节数组返回,如果字节已经没有可读的返回-1 |
方法名称 | 说明 |
---|---|
public int read() | 每次读取一个字节返回,如果字节已经没有可读的返回-1 |
public int read(byte[] buffer) | 每次使用字节数组来读取数据,返回读取的字节个数,如果没有可读返回-1 |
方式一
方法名称 | 说明 |
---|---|
public int read(byte[] buffer) | 每次读取一个字节数组返回,如果字节已经没有可读的返回-1 |
方式二
方法名称 | 说明 |
---|---|
public byte[] readAllBytes() throws IOException | 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回 |
构造器 | 说明 |
---|---|
public FileOutputStream(File file) | 创建字节输出流管道与源文件对象接通 |
public FileOutputStream(File file,boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileOutputStream(String filepath) | 创建字节输出流管道与源文件路径接通 |
public FileOutputStream(String filepath,boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
方法名称 | 说明 |
---|---|
public void write(int a) | 写一个字节出去 |
public void write(byte[] buffer) | 写一个字节数组出去 |
public void write(byte[] buffer , int pos , int len) | 写一个字节数组的一部分出去。 |
方法 | 说明 |
---|---|
flush() | 刷新流,还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
finally:在异常处理时提供finally块来执行所有清除操作,比如IO流中释放资源
特点:被finally控制的语句最终一定会执行,除非JVM退出
异常处理标准格式:try…catch…finally
格式:
try {
FileOutputStream fos = new FileOutputStream("a.txt");
fos.write(97);
} catch (IOException e) {
e.printStackTrace();
}finally{
}
构造器 | 说明 |
---|---|
public FileReader(File file) | 创建字符输入流管道与源文件对象接通 |
public FileReader(String pathname) | 创建字符输入流管道与源文件路径接通 |
方法名称 | 说明 |
---|---|
public int read() | 每次读取一个字符返回,如果字符已经没有可读的返回-1 |
public int read(char[] buffer) | 每次读取一个字符数组,返回读取的字符个数,如果字符已经没有可读的返回-1 |
构造器 | 说明 |
---|---|
public FileWriter(File file) | 创建字符输出流管道与源文件对象接通 |
public FileWriter(File file,boolean append) | 创建字符输出流管道与源文件对象接通,可追加数据 |
public FileWriter(String filepath) | 创建字符输出流管道与源文件路径接通 |
public FileWriter(String filepath,boolean append) | 创建字符输出流管道与源文件路径接通,可追加数据 |
方法名称 | 说明 |
---|---|
void write(int c) | 写一个字符 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
void write(String str) | 写一个字符串 |
void write(String str, int off, int len) | 写一个字符串的一部分 |
方法 | 说明 |
---|---|
flush() | 刷新流,还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
构造器 | 说明 |
---|---|
public BufferedInputStream(InputStream is) | 可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能 |
public BufferedOutputStream(OutputStream os) | 可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能 |
构造器 | 说明 |
---|---|
public BufferedReader(Reader r) | 可以把低级的字符输入流包装成一个高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能 |
字符缓冲输入流新增功能:
方法 | 说明 |
---|---|
public String readLine() | 读取一行数据返回,如果读取没有完毕,无行可读返回null |
构造器 | 说明 |
---|---|
public BufferedWriter(Writer w) | 可以把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能 |
字符缓冲输出流新增功能:
方法 | 说明 |
---|---|
public void newLine() | 换行操作 |
构造器 | 说明 |
---|---|
public InputStreamReader(InputStream is) | 可以把原始的字节流按照代码默认编码转换成字符输入流。几乎不用,与默认的FileReader一样。 |
public InputStreamReader(InputStream is ,String charset) | 可以把原始的字节流按照指定编码转换成字符输入流,这样字符流中的字符就不乱码了(重点) |
构造器 | 说明 |
---|---|
public OutputStreamWriter(OutputStream os) | 可以把原始的字节输出流按照代码默认编码转换成字符输出流。几乎不用。 |
public OutputStreamWriter(OutputStream os,String charset) | 可以把原始的字节输出流按照指定编码转换成字符输出流(重点) |
构造器 | 说明 |
---|---|
public ObjectOutputStream(OutputStream out) | 把低级字节输出流包装成高级的对象字节输出流 |
ObjectOutputStream序列化方法:
方法名称 | 说明 |
---|---|
public final void writeObject(Object obj) | 把对象写出去到对象序列化流的文件中去 |
注意:对象要序列化必须实现Serializable接口
构造器 | 说明 |
---|---|
public ObjectInputStream(InputStream out) | 把低级字节输如流包装成高级的对象字节输入流 |
ObjectInputStream序列化方法:
方法名称 | 说明 |
---|---|
public Object readObject() | 把存储到磁盘文件中去的对象数据恢复成内存中的对象返回 |
注意:transient修饰的变量不参与序列化,可以用它来修饰一些敏感字段
PrintStream
构造器 | 说明 |
---|---|
public PrintStream(OutputStream os) | 打印流直接通向字节输出流管道 |
public PrintStream(File f) | 打印流直接通向文件对象 |
public PrintStream(String filepath) | 打印流直接通向文件路径 |
方法 | 说明 |
---|---|
public void print(Xxx xx) | 打印任意类型的数据出去 |
PrintWriter
构造器 | 说明 |
---|---|
public PrintWriter(OutputStream os) | 打印流直接通向字节输出流管道 |
public PrintWriter (Writer w) | 打印流直接通向字符输出流管道 |
public PrintWriter (File f) | 打印流直接通向文件对象 |
public PrintWriter (String filepath) | 打印流直接通向文件路径 |
方法 | 说明 |
---|---|
public void print(Xxx xx) | 打印任意类型的数据出去 |
构造器 | 说明 |
---|---|
void load(InputStream inStream) | 从输入字节流读取属性列表(键和元素对) |
void load(Reader reader) | 从输入字符流读取属性列表(键和元素对) |
void store(OutputStream out, String comments) | 将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法的格式写入输出字节流 |
void store(Writer writer, String comments) | 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流 |
public Object setProperty(String key, String value) | 保存键值对(put) |
public String getProperty(String key) | 使用此属性列表中指定的键搜索属性值 (get) |
public Set stringPropertyNames() | 所有键的名称的集合 (keySet()) |
FileUtils主要有如下方法:
方法名 | 说明 |
---|---|
String readFileToString(File file, String encoding) | 读取文件中的数据, 返回字符串 |
void copyFile(File srcFile, File destFile) | 复制文件。 |
void copyDirectoryToDirectory(File srcDir, File destDir) | 复制文件夹。 |
JDK1.7开始,也做了一些一行代码完成复制的操作:New IO的技术
线程(thread)是一个程序内部的一条执行路径
我们之前启动程序执行后,main方法的执行其实就是一条单独的执行路径
程序中如果只有一条执行路径,那么这个程序就是单线程的程序
多线程是指从软硬件上实现多条执行流程的技术
构造器 | 说明 |
---|---|
public Thread(String name) | 可以为当前线程指定名称 |
public Thread(Runnable target) | 封装Runnable对象成为线程对象 |
public Thread(Runnable target ,String name ) | 封装Runnable对象成为线程对象,并指定线程名称 |
方法名称 | 说明 |
---|---|
public FutureTask<>(Callable call) | 把Callable对象封装成FutureTask对象。 |
public V get() throws Exception | 获取线程执行call方法返回的结果。 |
方式 | 优点 | 缺点 |
---|---|---|
继承Thread类 | 编程比较简单,可以直接使用Thread类中的方法 | 扩展性较差,不能再继承其他的类,不能返回线程执行的结果 |
实现Runnable接口 | 扩展性强,实现该接口的同时还可以继承其他的类。 | 编程相对复杂,不能返回线程执行的结果 |
实现Callable接口 | 扩展性强,实现该接口的同时还可以继承其他的类。可以得到线程执行的结果 | 编程相对复杂 |
方法名称 | 说明 |
---|---|
String getName() | 获取当前线程的名称,默认线程名称是Thread-索引 |
void setName(String name) | 将此线程的名称更改为指定的名称,通过构造器也可以设置线程名称 |
方法名称 | 说明 |
---|---|
public static Thread currentThread(): | 返回对当前正在执行的线程对象的引用 |
注意:
方法名称 | 说明 |
---|---|
public Thread(String name) | 可以为当前线程指定名称 |
public Thread(Runnable target) | 封装Runnable对象成为线程对象 |
public Thread(Runnable target ,String name ) | 封装Runnable对象成为线程对象,并指定线程名称 |
方法名称 | 说明 |
---|---|
public static void sleep(long time) | 让当前线程休眠指定的时间后再继续执行,单位为毫秒。 |
作用:把出现线程安全问题的核心代码给上锁
原理:每次只能一个线程进入,执行完毕后自动解锁,其他线程才可以进来执行
synchronized(同步锁对象) {
操作共享资源的代码(核心代码)
}
锁对象要求:
作用:把出现线程安全问题的核心方法给上锁
原理:每次只能一个线程进入,执行完毕以后自动解锁,其他线程才可以进来执行
格式:
修饰符 synchronized 返回值类型 方法名称(形参列表) {
操作共享资源的代码
}
底层原理:
方法名称 | 说明 |
---|---|
public ReentrantLock() | 获得Lock锁的实现类对象 |
方法名称 | 说明 |
---|---|
void lock() | 获得锁 |
void unlock() | 释放锁 |
线程通信通常是在多个线程操作同一个共享资源的时候需要进行通信,且要保证线程安全
方法名称 | 说明 |
---|---|
void wait() | 让当前线程等待并释放所占锁,直到另一个线程调用notify()方法或 notifyAll()方法 |
void notify() | 唤醒正在等待的单个线程 |
void notifyAll() | 唤醒正在等待的所有线程 |
注意:上述方法应该使用当前同步锁对象进行调用
线程池就是一个可以复用线程的技术
如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
ExecutorService pools = new ThreadPoolExecutor(3,5,8,TimeUnit.SECONDS,new ArrayBlockingQueue<>(6),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
方法名称 | 说明 |
---|---|
void execute(Runnable command) | 执行任务/命令,没有返回值,一般用来执行 Runnable 任务 |
Future submit(Callable task) | 执行任务,返回未来任务对象获取线程结果,一般拿来执行 Callable 任务 |
void shutdown() | 等任务执行完毕后关闭线程池 |
List |
立刻关闭,停止正在执行的任务,并返回队列中未执行的任务 |
策略 | 详解 |
---|---|
ThreadPoolExecutor.AbortPolicy | 丢弃任务并抛出RejectedExecutionException异常。是默认的策略 |
ThreadPoolExecutor.DiscardPolicy: | 丢弃任务,但是不抛出异常 这是不推荐的做法 |
ThreadPoolExecutor.DiscardOldestPolicy | 抛弃队列中等待最久的任务 然后把当前任务加入队列中 |
ThreadPoolExecutor.CallerRunsPolicy | 由主线程负责调用任务的run()方法从而绕过线程池直接执行 |
方法名称 | 说明 |
---|---|
void execute(Runnable command) | 执行任务/命令,没有返回值,一般用来执行 Runnable 任务 |
Future submit(Callable task) | 执行任务,返回未来任务对象获取线程结果,一般拿来执行 Callable 任务 |
void shutdown() | 等任务执行完毕后关闭线程池 |
List |
立刻关闭,停止正在执行的任务,并返回队列中未执行的任务 |
方法名称 | 说明 |
---|---|
public static ExecutorService newCachedThreadPool() | 线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了一段时间则会被回收掉。 |
public static ExecutorService newFixedThreadPool(int nThreads) | 创建固定线程数量的线程池,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程替代它。 |
public static ExecutorService newSingleThreadExecutor () | 创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。 |
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) | 创建一个线程池,可以实现在给定的延迟后运行任务,或者定期执行任务。 |
注意:Excutors的底层其实也是基于线程池的实现类ThreadPoolExcutor创建线程池对象的
方法名称 | 存在问题 |
---|---|
public static ExecutorService newFixedThreadPool(int nThreads) | 允许请求的任务队列长度是Integer.MAX_VALUE,可能出现OOM错误( java.lang.OutOfMemoryError ) |
public static ExecutorService newSingleThreadExecutor() | |
public static ExecutorService newCachedThreadPool() | 创建的线程数量最大上限是Integer.MAX_VALUE, 线程数可能会随着任务1:1增长,也可能出现OOM错误( java.lang.OutOfMemoryError ) |
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4juzAzWN-1684550850451)(.\img\线程池工具类陷阱.png)]
构造器 | 说明 |
---|---|
public Timer() | 创建Timer定时器对象 |
方法 | 说明 |
---|---|
public void schedule(TimerTask task, long delay, long period) | 开启一个定时器,按照计划处理TimerTask任务 |
1、Timer是单线程,处理多个任务按照顺序执行,存在延时与设置定时器的时间有出入
2、可能因为其中的某个任务的异常使Timer线程死掉,从而影响后续任务执行
Executors的方法 | 说明 |
---|---|
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) | 得到线程池对象 |
ScheduledExecutorService的方法 | 说明 |
---|---|
public ScheduledFuture> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) | 周期调度方法 |
public enum State {
NEW,//新建状态
RUNNABLE,//就绪状态
BLOCKED,//阻塞状态
WAITING,//等待状态
TIMED_WAITING,//计时状态
TERMINATED;//结束状态
}
线程状态 | 描述 |
---|---|
NEW(新建) | 线程刚被创建,但是并未启动。 |
Runnable(可运行) | 线程已经调用了start()等待CPU调度 |
Blocked(锁阻塞) | 线程在执行的时候未竞争到锁对象,则该线程进入Blocked状态;。 |
Waiting(无限等待) | 一个线程进入Waiting状态,另一个线程调用notify或者notifyAll方法才能够唤醒 |
Timed Waiting(计时等待) | 同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。带有超时参数的常用方法有Thread.sleep 、Object.wait。 |
Teminated(被终止) | 因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。 |
IPv6:128位(16个字节),号称可以为地球每一粒沙子编号
名称 | 说明 |
---|---|
public static InetAddress getLocalHost() | 返回本主机的地址对象 |
public static InetAddress getByName(String host) | 得到指定主机的IP地址对象,参数是域名或者IP地址 |
public String getHostName() | 获取此IP地址的主机名 |
public String getHostAddress() | 返回IP地址字符串 |
public boolean isReachable(int timeout) | 在指定毫秒内连通该IP地址对应的主机,连通返回true |
注意:我们自己开发程序选择注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错
OSI参考模型 | 各层对应 | 面向操作 |
---|---|---|
应用层 | HTTP、FTP、DNS、SMTP… | 应用程序需要关注的:浏览器,邮箱。程序员一般在这一层开发 |
表示层 | ||
会话层 | ||
传输层 | TCP、UDP… | 选择使用的TCP , UDP协议 |
网络层 | IP、ICMP… | 封装源和目标IP,进行路径选择 |
数据链路层 | 物理寻址、比特流… | 物理设备中传输 |
构造器 | 说明 |
---|---|
public DatagramPacket(byte[] buf, int length, InetAddress address, int port) | 创建发送端数据包对象 buf:要发送的内容,字节数组 length:要发送内容的字节长度 address:接收端的IP地址对象 port:接收端的端口号 |
public DatagramPacket(byte[] buf, int length) | 创建接收端的数据包对象 buf:用来存储接收的内容 length:能够接收内容的长度 |
方法 | 说明 |
---|---|
public int getLength() | 获得实际接收到的字节个数 |
构造器 | 说明 |
---|---|
public DatagramSocket() | 创建发送端的Socket对象,系统会随机分配一个端口号。 |
public DatagramSocket(int port) | 创建接收端的Socket对象并指定端口号 |
方法 | 说明 |
---|---|
public void send(DatagramPacket dp) | 发送数据包 |
public void receive(DatagramPacket p) | 接收数据包 |
单播:单台主机与单台主机之间的通信
广播:当前主机与所在网络中的所有主机通信
组播:当前主机与选定的一组主机的通信
注意:在java中只是使用java.net.Socket类实现通信,底层即是使用了TCP协议
构造器 | 说明 |
---|---|
public Socket(String host , int port) | 创建发送端的Socket对象与服务端连接,参数为服务端程序的ip和端口。 |
方法 | 说明 |
---|---|
OutputStream getOutputStream() | 获得字节输出流对象 |
InputStream getInputStream() | 获得字节输入流对象 |
构造器 | 说明 |
---|---|
public ServerSocket(int port) | 注册服务端端口 |
方法 | 说明 |
---|---|
public Socket accept() | 等待接收客户端的Socket通信连接 连接成功返回Socket对象与客户端建立端到端通信 |
注意:服务器必须给浏览器响应HTTP协议格式的数据,否则浏览器不识别
注解 | 说明 |
---|---|
@Test | 测试方法 |
@Before | 用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次。 |
@After | 用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次。 |
@BeforeClass | 用来静态修饰方法,该方法会在所有测试方法之前只执行一次。 |
@AfterClass | 用来静态修饰方法,该方法会在所有测试方法之后只执行一次。 |
注解 | 说明 |
---|---|
@Test | 测试方法 |
@BeforeEach | 用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次。 |
@AfterEach | 用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次。 |
@BeforeAll | 用来静态修饰方法,该方法会在所有测试方法之前只执行一次。 |
@AfterAll | 用来静态修饰方法,该方法会在所有测试方法之后只执行一次。 |
HelloWorld.java -> javac -> HelloWorld.class
Class c = HelloWorld.class;
方式一:Class c1 = Class.forName(“全类名”);
方式二:Class c2 = 类名.class
方式三:Class c3 =对象.getClass();
方法 | 说明 |
---|---|
Constructor>[] getConstructors() | 返回所有构造器对象的数组(只能拿public的) |
Constructor>[] getDeclaredConstructors() | 返回所有构造器对象的数组,存在就能拿到 |
Constructor getConstructor(Class>… parameterTypes) | 返回单个构造器对象(只能拿public的) |
Constructor getDeclaredConstructor(Class>… parameterTypes) | 返回单个构造器对象,存在就能拿到 |
符号 | 说明 |
---|---|
T newInstance(Object… initargs) | 根据指定的构造器创建对象 |
public void setAccessible(boolean flag) | 设置为true,表示取消访问检查,进行暴力反射 |
注意:反射可以破坏封装性,私有的也可以访问
方法 | 说明 |
---|---|
Field[] getFields() | 返回所有成员变量对象的数组(只能拿public的) |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
Field getField(String name) | 返回单个成员变量对象(只能拿public的) |
Field getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到 |
符号 | 说明 |
---|---|
void set(Object obj, Object value): | 赋值 |
Object get(Object obj) | 获取值。 |
方法 | 说明 |
---|---|
Method[] getMethods() | 返回所有成员方法对象的数组(只能拿public的) |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
Method getMethod(String name, Class>… parameterTypes) | 返回单个成员方法对象(只能拿public的) |
Method getDeclaredMethod(String name, Class>… parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
符号 | 说明 |
---|---|
Object invoke(Object obj, Object… args) | 运行方法 参数一:用obj对象调用该方法 参数二:调用方法的传递的参数(如果没有就不写) 返回值:方法的返回值(如果没有就不写) |
注意:如果某个方法是非public的,需要打开权限,然后再触发执行
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
// list.add(“黑马"); // 报错list.add(99);
public @interface 注解名称 {
public 属性类型 属性名() default 默认值 ;
}
方法 | 说明 |
---|---|
Annotation[] getDeclaredAnnotations() | 获得当前对象上使用的所有注解,返回注解数组。 |
T getDeclaredAnnotation(Class annotationClass) | 根据注解类型获得对应注解对象 |
boolean isAnnotationPresent(Class annotationClass) | 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false |
version:XML默认的版本号码、该属性是必须存在的
encoding:本XML文件的编码
XML文件可以定义注释信息:
XML文件中可以存在以下特殊字符
< < 小于
> > 大于
& & 和号
' ' 单引号
" " 引号
XML文件可以存在CDATA区:
名称 | 说明 |
---|---|
JAXP | SUN公司提供的一套XML的解析的API |
JDOM | JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。 |
dom4j | 是JDOM的升级品,用来读写XML文件的。具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom 技术,同时它也是一个开放源代码的软件,Hibernate也用它来读写配置文件。 |
jsoup | 功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UkWxal4L-1684550850458)(.\img\DOM解析文档对象模型.png)]
SAXReader类
构造器/方法 | 说明 |
---|---|
public SAXReader() | 创建Dom4J的解析器对象 |
Document read(String url) | 加载XML文件成为Document对象 |
Document类
方法名 | 说明 |
---|---|
Element getRootElement() | 获得根元素对象 |
Dom4j解析XML的元素、属性、文本
方法名 | 说明 |
---|---|
List elements() | 得到当前元素下所有子元素 |
List elements(String name) | 得到当前元素下指定名字的子元素返回集合 |
Element element(String name) | 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个 |
String getName() | 得到元素名字 |
String attributeValue(String name) | 通过属性名直接得到属性值 |
String elementText(子元素名) | 得到指定名称的子元素的文本 |
String getText() | 得到文本 |
方法名 | 说明 |
---|---|
Node selectSingleNode(“表达式”) | 获取符合表达式的唯一元素 |
List selectNodes(“表达式”) | 获取符合表达式的元素集合 |
方法名 | 说明 |
---|---|
/根元素/子元素/孙元素 | 从根元素开始,一级一级向下查找,不能跨级 |
方法名 | 说明 |
---|---|
./子元素/孙元素 | 从当前元素开始,一级一级向下查找,不能跨级 |
方法名 | 说明 |
---|---|
//contact | 找contact元素,无论元素在哪里 |
//contact/name | 找contact,无论在哪一级,但name一定是contact的子节点 |
//contact//name | contact无论在哪一种,name只要是contact的子孙元素都可以找到 |
方法名 | 说明 |
---|---|
//@属性名 | 查找属性对象,无论是哪个元素,只要有这个属性即可。 |
//元素[@属性名] | 查找元素对象,全文搜索指定元素名和属性名。 |
//元素//[@属性名=‘值’] | 查找元素对象,全文搜索指定元素名和属性名,并且属性值相等。 |
InputStream(抽象父类)
FileInputStream(实现子类,读写性能较差)
BufferedInputStream(实现子类,装饰类,读写性能高)
名称 | 说明 |
---|---|
JAXP | SUN公司提供的一套XML的解析的API |
JDOM | JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。 |
dom4j | 是JDOM的升级品,用来读写XML文件的。具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom 技术,同时它也是一个开放源代码的软件,Hibernate也用它来读写配置文件。 |
jsoup | 功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便 |
SAXReader类
构造器/方法 | 说明 |
---|---|
public SAXReader() | 创建Dom4J的解析器对象 |
Document read(String url) | 加载XML文件成为Document对象 |
Document类
方法名 | 说明 |
---|---|
Element getRootElement() | 获得根元素对象 |
Dom4j解析XML的元素、属性、文本
方法名 | 说明 |
---|---|
List elements() | 得到当前元素下所有子元素 |
List elements(String name) | 得到当前元素下指定名字的子元素返回集合 |
Element element(String name) | 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个 |
String getName() | 得到元素名字 |
String attributeValue(String name) | 通过属性名直接得到属性值 |
String elementText(子元素名) | 得到指定名称的子元素的文本 |
String getText() | 得到文本 |
方法名 | 说明 |
---|---|
Node selectSingleNode(“表达式”) | 获取符合表达式的唯一元素 |
List selectNodes(“表达式”) | 获取符合表达式的元素集合 |
方法名 | 说明 |
---|---|
/根元素/子元素/孙元素 | 从根元素开始,一级一级向下查找,不能跨级 |
方法名 | 说明 |
---|---|
./子元素/孙元素 | 从当前元素开始,一级一级向下查找,不能跨级 |
方法名 | 说明 |
---|---|
//contact | 找contact元素,无论元素在哪里 |
//contact/name | 找contact,无论在哪一级,但name一定是contact的子节点 |
//contact//name | contact无论在哪一种,name只要是contact的子孙元素都可以找到 |
方法名 | 说明 |
---|---|
//@属性名 | 查找属性对象,无论是哪个元素,只要有这个属性即可。 |
//元素[@属性名] | 查找元素对象,全文搜索指定元素名和属性名。 |
//元素//[@属性名=‘值’] | 查找元素对象,全文搜索指定元素名和属性名,并且属性值相等。 |
InputStream(抽象父类)
FileInputStream(实现子类,读写性能较差)
BufferedInputStream(实现子类,装饰类,读写性能高)