java高级
一、常用API
1、Object类
1、作用:
(1)它是java中任何引用类的父类。包括我们自己定义的类、和java类库中的类。
(2)任何的引用类都从Object类中继承了一些方法。例如:toString()、equals()方法。
2、使用:
(1)它是java.lang包下的。
3、方法:
toString():打印所有的属性的值。(我们的类需要重写此方法)
equals():比较“两个对象”的所有属性值是否完全相同。
2、Objects类
1、作用:
此类内部定义了大量的对"对象"操作的一些"静态方法。
2、使用:
(1)它是java.util包下的。
3、方法:
equals:此方法可以比较两个对象“是否完全相同”。(此方法也是基于我们对象的equals()方法进行判断的
4、Object的equals和Objects的equals方法的比较。
(1)Object的equals方法。如果对象不一样。会抛出空指针异常
(2)Objects的equals方法。不会抛出空指针异常。
(3)对于“空引用”,Objects的equals()方法更安全。
3、Date类(日期类)
1、作用:
它代表了一个特定的时间,精度:毫秒。
2、使用:
(1)它是java.util包下的。
(2)构造方法:
Date():使用当前系统时间构造一个Date对象。
Date(long m):使用一个“毫秒值”构造一个Date对象。
3、方法:
getTime():获取毫秒值。
setTime(long m):设置毫秒值。
4、DateFormat类(日期格式)
1、作用:
DateFormat(抽象类)它可以对Date进行“格式化显示”的一个工具类。
2、使用:
(1)它在java.text包下
(2)此类是一个“抽象类”,不能直接创建对象,可以使用它的子类。
(3)java.text.SimpleDateFormat(子类)
3、构造方法:
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss);
4、方法:
parse():将String转换为Date格式(此格式必须跟字符串中的日期格式“匹配”否则抛异常)。
format():将Date转换为String。
5、Calendar类(日历类)
1、作用:
Calendar(抽象类):它代表一个“日历”,可以进行日期运算。使用他的子类GregorianCalendar
2、使用:
(1)它是java.util包下的。
(2)使用格式:(简单的方式获取这个子类对象)
Calendar c = Calendar.getInstance();
3、方法:
get(): 获取某字段值。例如:int year = c.get(Calendar.YEAR);(月需要加一处理)。
set():设置某字段值。例如:把c设置为1996年 c.set(Calendar.YEAR,1996)。
add():将某字段增加指定的值。例如:设置100天后 c.add(Calendar.DAY_OF_MONTH,100);
6、System类(系统类)
1、作用:
它包含了一些实用的“静态方法”。
2、使用:
(1)它是java.lang包下的。
3、方法:
arraycopy:复制数组。
格式:arraycopy(原数组,原数组的起始位置,目标数组,目标数组的索引位置,复制的数量)
currentTimeMillis:获取当前系统时间的毫秒值。
exit:结束JVM。(也就是结束程序)。
格式:System.exit(0);
7、StringBuilder字符串拼接
1、作用:
(1)由于String的不可变性,导致做“字符串连接”时,效率低下。Java为我们提供了一种类:StringBuilder专门做“字符串连接”的。
(2)区别:
String拼接字符串会在内存中创建新的空间。
StringBuilder不会创建新的空间,直接向原来存储字符串空间里面进行添加。
2、使用:
(1)它是java.lang包下的。
3、构造方法:
StringBuilder():构造一个有16个空位置的StringBuilder对象。
StringBuilder("Hello")
4、方法:
append() :拼接各种类型的数据。
reverse():将拼接的字符串进行反转。
toString(): 打印字符串。
8、StringBuffer类
1、它是:
java.lang 包下的类
2、作用:
它也可以进行字符串拼接,
3、区别:
(1)StringBuffer类是线程安全的,StringBuilder线程不安全【不能同步访问】,但是速度快。
(2)然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。
9、包装类
1、作用:
将基本类型转换成对象。方便操作。
2、基本类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
3、包装类常用方法(除Character类。其余的可以将字符串转换为自己的那种类型)
toString() : 将某种类型转换为字符串。
parse类型() : 将字符串转换为某种类型。例如:parseByte()、parseShort()。
4、装箱和拆箱的好处。
(1)装箱:将"基本类型"赋值给“包装类型”。
(2)拆箱:将"包装类型"赋值给"基本类型"。
(3)好处:将"包装类型"与"基本类型"可以等同看待,操作起来比较方便。
二、集合
1、集合概述
1、作用:
集合是一个容器用来存储数据。它只能保存引用类型 (也就是只能保存对象,基本类型通过包装类来完成)
2、它和数组的区别:
(1)数组:长度固定的。集合:长度不固定。
(2)数组中存储的是同一类型的元素,,可以存储基本数据类型值。集合储存的都是引用类型。对象的类型可以不一致。
3、集合的分类(两大类)
(1)单列集合 【Collection】
(2)双列集合 【Map】
3、常见的数据结构
(1)数组:ArrayList
(2)链表:LinkedList
(3)哈希表:HashSet【它地层是:数组+链表+红黑树实现】
(4)栈
(5)队列
(6)树
(7)图
2、数据结构
1、介绍:
数据结构存是指储数据的方式。不同的存储方式,会影响增、删、改、查操作的效率。
2、数据结构介绍:
(1)数组:
a、地层原理:内存中是“连续的”,通过索引访问;
b、特点:查询快;增删慢。
(2)链表:
a、地层原理:多个节点通过记录地址连接的。
b、特点:查询慢;增删快。
(3)哈希表特点:
1).不存储重复元素;
2).JDK8后,使用的是数据结构:数组 + 链表 + 红黑树;
3).验证元素唯一性的方式:
1).先比较元素的hashCode()
不同:存
相同:比较元素的equals()
不同:存
相同:不存
(4)栈:
a、地层原理:添加、删除都在同一端;(1)压栈:就是存元素。(2)弹栈:就是取元素。
b、特点:先进后出。
(5)队列:
a、地层原理:添加、删除各占一端。
b、特点:先进先出。
(6) 树:【红黑树(二叉树)】
就是一种类似于我们生活中树的结构,只不过每个结点上都多只能有两个子结点。二叉树是每个节点多有两个子树的树结构。顶上的叫根结点,两边被称作“左子树”和“右子树”。
3、Collection(单列集合)
1、介绍:
(1)它是单列集合类的根接口,他有两个重要的子接口List、Set。
(2)List的特点:是元素有序、元素可重复。
(3)Set的特点:元素无序,而且不可重复。
2、单例集合通用的方法:
add(): 添加到当前集合中。(添加到集合的尾部)
clear() :清空集合中所有的元素。
remove() :从集合中删除。(注意:如果有多个相同元素,只移除一个)
contains():判断当前集合中是否包含给定的对象。
isEmpty():判断当前集合是否为空。
size() :返回集合中元素的个数。
toArray() : 把集合中的元素,存储到数组中。
List集合
1、特点:
(1)存储的元素是有序的;(2).可以存储重复元素。
2、List接口中新增对索引操作的方法:
add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上
get(int index) :返回集合中指定位置的元素。
remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。
set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
3、它的实现类
ArrayList、LinkedList
4、ArrayList集合特点:
存储的结构是数组结构。元素增删慢,查找快。
5、LinkedList集合:
存储的结构是双向链表结构。方便元素添加、删除的集合。(它也可以作为堆栈,队列的结构使)。
6、LinkedList对首尾操作的特有方法:
addFirst() :将指定元素插入此列表的开头。
addLast() :将指定元素添加到此列表的结尾。
getFirst() :返回此列表的第一个元素。
getLast() :返回此列表的后一个元素。
removeFirst() :移除并返回此列表的第一个元素。
removeLast() :移除并返回此列表的后一个元素。
poll() :弹栈从集合中取出数据。
push(E e) :压栈装入集合。
boolean isEmpty() :如果列表不包含元素,则返回true。
Set集合
1、特点:
(1)存储的元素是无序的;
(2)不能存储重复元素;
2、子类(实现类)
HashSet(哈希表实现)、LinkedHashSet(链表、哈希表实现,它是特例:它是有序的,是它自己的顺序。)。
3、哈希表:
在JDK1.8之前,哈希表采用地层采用的是数组+链表。JDK1.8中使用的是数组+链表+红黑树实现。是先判断元素的hashCode(),再判断元素的equals()。不同在进行存储。
4、Collections单例集合工具类
1、作用:
里面包含了对Collection集合操作的一些工具性方法。
2、使用:
(1)java.util.Collections(工具类)包下。
3、常用的静态方法:
addAll(集合名, 参数1,参数2......) :往集合中添加一些元素。
shuffle(集合名) 打乱顺序 :打乱集合顺序。
sort(集合名) :将集合元素进行默认排序。
(1)注意:对集合元素排序,是基于元素的compareTo()方法排序。(必须实现Comparable接口)
sort(集合名,new Comparator<? super T> :将集合中元素按照指定规则排序。
(1)注意:使用“比较器”对集合元素进行排序。使用匿名内部类来完成
5、比较器
1、比较器Comparable和Comparator的区别:
他们都是比较器。作用一样。用法不一样。
2、Comparable(接口):
(1)特点:
强行对它的实现类的对象进行整体排序。这种排序被称为类的自然排序。类的compareTo方法 被称为它的自然比较方法。
(2)缺点:
在类需要实现Comparable接口。使用compareTo()方法进行排序,排序的灵活性被限制。只能是这一种排序方式。
3、Comparator(接口):
(1)特点:
强行对某个对象进行整体排序。可以将Comparator 传递给sort方法。
(2)好处:
(1)使用集合工具类的sort方法,进行自定义对象排序的时候,自定义类不用继承任何类。它可以直接将对象传进去进行排序。
(2)更灵活。对对象排序不用动源码。
6、Map(双列集合)
Map概述
1、特点:
1).Map内部采用“键值对”的形式存储;
2).在一个Map内,“键”是唯一的;
3).键和值可以是任何对象;
4).可以通过“键”获取对应的“值”;
2、它的常用实现类:
注意:Map集合的存储结构只对“键”进行处理。值不进行处理。
HashMap(子类):键是“哈希表”结构。
LinkedHashMap(子类):键是“链表、哈希表”结构;【通过链表结构可以保证元素的存取顺序一致】
3、Map内部类Entry介绍:
它是Map的内部类,将Map中的每一个键值对,进行一一对应的封装成一个对象。【其实就是Map中的每一个键值对就是一个Entry对象】
3、方法:
(1)添加、修改(使用的同一个方法):
put():添加。【如果存储的键相同,新值‘替换’旧值,并返回旧值】
(2)删除:
remove(Object key):使用键删除对应的“键值对。【将键和值都进行删除】
(3)查询:
get(K key):通过键或取对应的值。
size():获取键值对的数量。
keySet() :获取Map集合中所有的键,返回类型是Set集合。
entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)。
(4)遍历:
注意:Map本身没有遍历的方法,都是间接遍历。
1).键找值:keySet()。获取所有的的key进行遍历。根据key获取值。
2).获取“键值对所有的对象”的方式;entrySet()。
HashMap
1、注意事项:
自定义对象做键,自定义对象必须重写hashCode()和equals()方法。不然键重复也能存进去。
2、执行原理:
因为Map地层存储的是Entry对象。每个对象在内存中堆中地址是不一样的。不重写hashCode()和equals()方法。那么它只是比较地址是否相同。不同进行存储。重写后会进行比较对象里面的值是否一样。
LinkedHashMap
1、注意事项:
它是Map的特例,有序的哈希表;储存的顺序有序。
7、JDK9对集合添加的优化
1、介绍:
JDK9对List、Set、Map集合提供了一种静态方法:of() 。
2、例如:
List<String> strList = List.of("张三","李四","王五","周六");
Set<String> strSet = Set.of("黄渤","黄老邪","黄磊","黄瓜");
Map<Character,Integer> map = Map.of('a',10,'b',20,'c',25);
3、特点:
它们返回都是:(长度)不可变的集合。不能对元素进行添加、删除等操作;
三、泛型
1、概述和使用
1、介绍:
可以在类或方法中预支地使用未知的类型。泛型用来规范集合用的。
2、泛型的好处:
(1)让编译器为我们的代码监督,只能向集合中添加同一种类型的数据,
(2)泛型,可以用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。
(3)什么时候使用什么时候确定泛型。
3、使用:
(1)泛型类的定义格式:
修饰符 class 类名<代表泛型的变量> { }
(2)含有泛型的方法:
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
(3)含有泛型的接口 :
修饰符 interface接口名<代表泛型的变量> { }
4、泛型的统配符:
<?> : 表示可以接收任何泛型的集合。(注意:使用泛型统配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用)
5、泛型的上限、下限。
(1)上限:
格式:
类型名称 <? extends 类 > 对象名称 。
意义:
只能接收该类型及其子类。
(2)下限:
格式:
类型名称 <? super 类 > 对象名称 。
意义:
只能接收该类型及其父类型 。
四、异常
1、介绍
1、异常介绍:
是指程序在“运行时”。JVM遇到了无法处理的数据,或者表达式。这种情况就叫:异常。
2、异常体系:
Throwable(顶层的异常父类)
|--Error(错误)异常中不建议捕获的重大错误;例如:内存溢出等。
|--Exception(异常)希望我们程序捕获并处理的异常情况,处理后程序可以继续运行下去。
|--RuntimeException(运行时异常)程序可以不处理。
|--除RuntimeException外其它的异常类都是(编译期异常)程序必须处理,否则编译错误。
3、虚拟机处理异常的方式:
1).JVM执行到有异常的代码;
2).JVM要识别出这种异常;
3).JVM到类库中找到对应的异常类,并创建对象;
4).判断代码中是否捕获(try catch)这种异常
是:执行catch进行捕获
否:在控制台打印异常信息,结束程序。
2、常见的异常
1、空指针异常:NullPointerException(运行时异常)
2、数组下标越界异常:ArrayIndexOutOfBoundsException(运行时异常)
3、数字转换异常:NumberFormatException(运行时异常)
4、算术运算异常:ArithmeticException(运行时异常)
5、转换异常:ParseException(编译期异常)--必须要捕获,否则编译错误
3、异常处理
1、异常的捕获:
try{
//可能出现异常的代码
}catch(异常类名 变量名){
//如果try中出现了“异常类名”的异常,这里会被捕获,
//会执行这里的代码。
//catch可以有多个但是有异常只会执行一个。
}finally{
//不管有没有异常都会执行。
//它一般情况可以不要。
}
2、声明抛出异常【throws】
表示“声明”此方法可能会产生某种异常,如果产生,请JVM将此异常对象抛给调用者。如果没有产生异常,则正常执行完毕。
3、抛出异常【throw】
表示立即“抛出一个异常对象”。
4、自定义异常
1、自定义异常注意事项:
(1)自定义异常类必须继承Exception或者它的某个子类 (RuntimeException/非RuntimeException(建议));
(2)建议:添加一个String参数的构造方法,用于设置“异常信息”
2、格式:
public class AgeException extends Exception{
public AgeException(String msg) {
super(msg);
}
}
五、多线程
1、概述
1、进程概念:
什么是“进程”:“进程”是操作系统的概念,一个独立运行的程序,就是一个“进程”。
2、线程的概念:
什么是“线程”:“线程”是由“进程创建”的,一个进程可以创建任意多的线程,每个线程都包含一些代码。线程中的代码会同主线程或者其他线程“同时运行”。
3、什么是“多进程:
在某个时间段内,同时运行多个程序。
4、什么是“多线程”:
一个程序可以同时启动多个线程,也就意味着可以使多段代码“同时运行”,可以提高程序的运行效率。
5、并行:
多个线程同时开始运行。
6、并发:
多个线程同时访问同一资源(CPU)。
7、进程与线程的区别:
进程:有独立的内存空间,进程中的数据存放空间(进程:堆空间、线程栈空间)是独立的,它至少有一个线程。
线程:堆空间是共享的,栈空间是独立的,线程消耗的资源比进程小的多。
8、注意事项:
(1)线程并发运行其实是有先后顺序的,那个线程先执行那个线程后执行,完全取决于电脑的CPU调度。
(2)java的进程至少包含两个线程。主进程main()方法,和垃圾回收机制线程。每当java执行一个类时,都会启动一个JVM,能JVM就是一个线程。Java本身具备了垃圾的收集机制。所以在 Java 运行时至少会启动两个线程。
9、线程的调度:
JVM采用的是抢占式调度,没有采用分时调度, 因此可以能造成多线程执行结果的的随机性。
2、多线程运行的原理
每一个线程在内存中,都有一个独立的栈空间。进行方法的压栈弹栈。当执行完线程执行完之后,线程自动在栈内存中释放。当执行的所有线程结束了,那么进程就结束了。
3、Thread 类
1、作用:
它是java提供线程类,使用线程必须继承它。
2、使用格式:
(1)它是java.lang包下的
(2)自定义线程类,需要继承自Thread,并重写run()方法:。run方法中是线程要执行的代码。
(3)在调用处使用start()启动线程;
3、注意事项:
(1).重写的是run(),但启动线程是:start();
(2).对于“一个线程对象”,只能调用一次start();
(3).对于“一个线程类”,可以创建多个线程对象,每个线程对象都可以以独立的。
4、构造方法:
Thread() :分配一个新的线程对象。
Thread(String name) :分配一个指定名字的新的线程对象。
Thread(Runnable target) :分配一个带有指定目标新的线程对象。
Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。
5、常用方法:
getName() :获取当前线程名称。
start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。
run() :此线程要执行的任务在此处定义代码。
sleep(long millis) :让当前的线程进行休息多长时间。
currentThread() :返回对当前正在执行的线程对象的引用。
4、Runnable接口
1、作用:
实现它重写run方法。也可以作为线程。但是它不是线程。还需要借助Thread线程类。
2、使用:
(1)它是java.lang包下的
3、使用格式:
(1)创建类实现Runnable接口重写run()方法。
(2)创建Thread类构造方法参数是(实现Runnable接口的自定义类)
(3)启动使用start()方法。
4、注意事项:
(1)自定义类实现了Runnable接口,并没有继承自Thread,所以不是一个“线程”。
(2)这种方式仍然需要Thread。
(3)可以将一个自定义类的对象,传给多个Thread。
5、Thread、Runnable的区别
1、区别:
(1)第一种方式需要子类继承自Thread。由于Java是“单继承”,所以对子类造成了不方便。
(2)第二种方式需要子类实现Runnable接口。Java允许一个类同时实现多个接口,所以对于子类。
6、匿名内部类实现线程
//方式一:Thread的匿名子类
new Thread(){
//线程执行的代码块
}.start();
//方式二:Runnable的匿名子类
new Thread(new Runnable(){
//线程执行的代码块
}).start();
7、线程同步
1、容易出现的问题:
当多线程共同访问同一共享资源时,就会产生:安全性问题。例如:多个线程队全局变量进行++处理就会出现问题。
2、解决方案:
(1)同步锁【使用synchronized 关键字来完成的】:
同步锁只是一个概念。意思就是给一个对象添加一个标记,表示锁的意思。谁先拿到谁先执行。等它执行完之后下一个在进行执行。【就是多个线程使用同一把锁。】
(2)Lock锁:它java提供了比synchronized代码块和synchronized方法更广泛的锁。
3、同代码块作用:【synchronized 关键字】
在方法中的某个区块使用synchronized关键字,进行对这个区块的资源实行互斥访问【使用它可以完成多线程同步锁。】
4、使用格式:
//注意使用在方法中
synchronized(同步锁【同步锁:可以是任何】){
//需要同步操作的代码
}
5、Lock锁作用:
(1)它是一个接口。需要使用它的实现类。;
Lock锁也称同步锁,加锁与释放锁方法进行了简化。比使用synchronized关键字完成同步锁更加的简单。
6、Lock锁常用方法:
lock() :加同步锁。
unlock() :释放同步锁。
7、使用格式:
Lock l = new 它的实现类;
l.lock(); //加锁
try {
//代码块
} finally {
l.unlock(); //解锁
}
8、线程的状态
1、新建:表示刚创建线程
2、可运行或者待运行:表示线程在java虚拟机中正在运行自己的代码,也可能没有运行。
3、锁阻塞: 当一个线程试图获取一个对象锁,但是对象锁被其他线程拿走了,那么该线程进入等待转态。
4、无限等待:一个线程在等待另外一个线程(唤醒)。这等待的过程就叫做无限等待。
5、计时等待:运行后,被调用了sleep()方法;
6、被终止:run()方法正常运行完毕。或者有异常导致run方法死亡。
9、线程等待与唤醒使用
1、作用:
就是一个线程在等待状态不能允许,需要另外一个线程唤醒后才能运行。
2、使用的方法:
锁对象.wait():表示等待唤醒,进入无限等待状态。
锁对象.notifyAll():表示唤醒当前持有本锁的线程
3、等待唤醒机制的通信:
(1)当一个工作需要多个线程同时配合完成,这样就需要多个线程之间进行“通信”,以保证这个工作能够完整的完成。这种相互配合的方式:线程间通信。
(2)“等待与唤醒机制”就是“线程间通信”的一种体现。
(3)例如:
1).一个线程做一些“准备性工作”。
2).另一个线程做正常的工作。
(1)由于两个线程是“无序的”,很有可能“第二个线程工作时,第一个线程的准备工作还没有做好,
(2)这时就需要第二个线程要主动“等待”
(3)然后第一个线程进入开始做准备,准备工作做好后,
(4)再唤醒第二个线程开始正常工作。
10、线程池
1、线程池的概念:
(1)线程池:就是存储了若干多的“线程对象”的一个“容器。
(2)对于一个线程对象“只能启动一次”,若想第二次再用,就需要再次创建一个线程对象,但如果创建线程对象很耗时。这样如果程序中要反复的使用同一个线程,整个程序的效率就会很低。
(3)线程池的思想:在程序启动时,会先创建若干多的线程对象,并存储到一个容器中,作为“线程池”。如果有需要时,取出一个线程对象,并执行它。执行完毕,线程池会回收这个线程对象。如果再次需要,可以再次取出,并执行它。所以,线程池中的线程对象是“可以反复重用”的。这样就避免的反复的创建线程对象,从而提高程序的执行效率。
11、ExecutorService线程池类
1、介绍:
java里面线程池的顶级接口是 Executor 、,但是严格意义上讲 Executor 并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是 ExecutorService 。
2、Executor:
java在Executor线程工厂类里面提供了一些静态工厂,可以生成一些常用的线程池。
3、ExecutorService:
它是线程池类。通过Executor静态工厂进行生产的。
4、方法:
newFixedThreadPool((int nThreads):返回线程池对象。参数是线程池里面线程的存储数量。
submit(Runnable task):获取线程池中的某一个线程对象,并执行 。第一次进行缓存。
shutdown():关闭线程池。
5、线程池的创建和使用:
//使用线程池
ExecutorService service = Executors.newFixedThreadPool(2);
//创建线程对象
MyThread t = new MyThread();//5秒
//第一次执行此线程--交给"线程池”去执行,线程池执行后,会将此线程对象"缓存",可以重用
service.submit(t);
//第二次执行此线程【从线程池中获取】
service.submit(t);
//第三次执行此线程【从线程池中获取】
service.submit(t);
//关闭线程池
service.shutdown();
六、函数式编程Lambda
1、Lambda概念
1、作用:
Lambda是匿名内部类的简写。
2、简化的变化过程:
内部类 ——> 匿名内部类 ——> Lambda表达式 ——> 方法引用。【作用:都是内部类】
3、Lambda表达式思想:
(1)将编程思想转换成“函数式”编程思想。也就是“以什么形式做”,转换为“怎样做”。
(2)Lambda更关注的是“怎么做”,不是以“什么形式去做”。
(3)优点:语法简洁。
4、Lambda表达式使用前提:
必须是函数式接口。
2、Lambda的使用
1、标准格式:
1).一对小括号--形参
2).一个箭头:->
3).一对大括号--方法体
2、省略格式:
1).形参:Lambda中的"形参类型”都可以省略;
2).形参:如果只有一个形参,形参类型和小括号都可以省略。【注意:要省略小括号,必须省略数据类型】
3).方法体:如果方法体中只有一条语句,可以使用省略规则。
A).有返回值:可以省略大括号、return关键字、语句后的分号【注意:要省全省,要用全用】
B).无返回值:可以省略大括号、语句后的分号;【注意:要省全省,要用全用】
3、函数式接口
1、函数式接口:
有,且“只有一个抽象方法” 的接口叫:函数式接口。
2、@FunctionalInterface注解:该注解可用于在一个接口上。
一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。
4、方法的引用
1、理解:
使用已有的方法。来完成对函数式接口中的抽象方法的重写。也就是“方法代替”。(使用已有的方法代替函数中的抽象方法)
2、方法引用的要求:
引用的方法”的形参、返回值类型,必须与被替换的"函数式接口”中抽象方法的一致。
3、引用表达式:
双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方 法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。
4、好处:
(2)代码更简介。
(3)开发效率高。
5、静态方法的引用
1、使用格式:
类名::方法名。
2、注意事项:
(1)必须通过"类名"引用,不能通过"对象名"引用。
(2)格式:
类名::方法名。
6、成员方法的引用
1、使用格式:
格式一:
类名 对象名=new 类;
对象名::方法名。
格式二:
new 类 ::方法名
7、super、this的方法引用
1、注意:
super、this只能用在子类中。
2、使用格式:
super::方法名;//表示使用引用父类的方法。
this::方法名;//表示使用引用当前类的方法。
8、构造方法的引用
1、无参构造方法的引用格式:
类名::new //相当通过引用当前类的无参构造方法,创建一个无参构造方法的对象。
2、有参构造方法的使用:
类名::new,参数 //表示通过构造参数创建一个有参构造对象。
9、常用函数接口
1、Supplier生产
1、生产者接口Supplier作用:
(1)可以用作lambda表达式或方法引用的赋值对象。
(2)没有要求每次调用供应商时都会返回新的或不同的结果。
2、特点:
1.只生产数据,不接收参数。在里面操作完之后,返回一个值。
3、使用格式:(使用它需要一个传递一个引用类型)
Supplier <类型> //表示:使用它当作方法的参数,那么 <> 中的类型是什么它就是返回什么类型的参数。
4、抽象方法:
T get();
2、Consumer消费
1、消费接口Consumer作用:
(1)可以用作lambda表达式或方法引用的赋值对象。
(2) 表示接受单个输入参数并且不返回结果的操作。
2、特点:
只接受参数,无返回值。
3、抽象方法:
accept():只接受参数,无返回值。
4、默认方法:
andThen():将两个Consumer对象的accept()方法的结果连在一起。
5.使用格式:
Consumer <类型> //使用它当作方法的参数。那么参数是什么 ,<> 中的类型就写什么。
参数格式例如:Consumer <String> con,String s
3、Predicate判断
1、作用:
(1)因此可以用作lambda表达式或方法引用的赋值对象
(2)对某种类型的数据进行判断,得到一个boolean值结果。
2、抽象方法:
trst():返回boolean类型。
3、默认方法:
and():判断两个Predicate是否,是并且关系:
or(): 或者
nwgate(): 非
4、使用格式:
Predicate <类型> //使用它当作方法的参数。那么参数是什么 ,<> 中的类型就写什么。
参数格式例如:Predicate<String> p , String s
4、Function转换
1、作用:
(1)因此可以用作lambda表达式或方法引用的赋值对象。
(2)表示接受一个参数并产生结果的函数。
(3)通常用来做转换。接受一种类型,转换成另外一种类型。
2、抽象方法:
apply(T t): 将此函数应用于给定的参数。
3、默认方法:
andThen():将两个apply方法连接起来。
4、使用格式:
Function<类型1,类型2>//将类型1,转成类型2。
10、延迟方法、终结方法
1、概述:
是指函数式接口中的延迟方法和终结方法。
2、区别:
(1)延迟方法:只是在拼接Lambda函数模型的方法, 并不立即执行得到结果。
(2)终结方法:根据拼好的Lambda函数模型, 立即执行得到结果值的方法。
3、备注:
JDK中更多内置的常用函数式接口,请参考 java.util.function 包的API文档。
11、Stream流
1、概述
1、在Java 8中,得益于Lambda所带 来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊端。
2、简单的理解:
它就是一个对集合进行操作的“工具类”。里面包含很多对集合操作的方法。尤其是进行筛选、过滤、求总数量....等一系列操作时。
使用Stream流 + Lambda表达式,就非常的方便。
2、Stream流的获取
1、通过集合对象获取Stream流:
(1)List集合获取流:
List<String> list = new ArrayList<>();
//获取流
Stream<String> s = list.stream();
(2)Set集合获取流:
Set<String> set = new HashSet<>();
//获取流
Stream<String> s = set.stream();
(3)Map集合获取流:
Map<String,String> map = new HashMap<>();
//Key获取流
Stream<String> keyStream = map.keySet().stream();
//Value获取流
String<String> valueStream = map.values().stream();
2、通过“数组”获取流:
(1)零散的数据:
A、零散数据这里是指,用 Stream 接口的 of()方法来获取零散的数据,它不是集合也不是数组,是单个的数据,通过整理也能获取流,对它们进行操作。
Stream<String> s1 = Stream.of("a", "b", "c", "d");
(2)通过"数组"获取流
Integer[] arr = {10, 20, 30, 40};//必须是引用类型数组
Stream<Integer> s2 = Stream.of(arr);
(3)基本类型数组:
int[] arr2 = {10, 20, 30, 40};
IntStream s3 = IntStream.of(arr2);
3、常用方法
1、使用注意事项:
(1)流的延迟方法还会返回流本身,还可以继续调用,可以使用方法链。
(2)终结方法:
方法执行完后,返回的值类型不再是Stream流类型,因此不再支持类似StringBuilder那样的链式调用。
(3)延迟方法:
返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。
2、终结方法:
count() : 统计个数。
forEach(): 逐个处理。
3、延迟方法:
filter():过滤。返回对错
limit():取前几个。
skip():跳过前几个。
七、IO流
1、File类
1、作用:
它可以表示磁盘上的一个文件或者目录。使用它可以获取磁盘上的文件/目录的一些属性信息。
例如:
1).文件/目录名;
2).文件的大小;
3).文件/目录的最后修改时间;
4).文件/目录的是否可读、是否可写。
2、构造方法:
File file1 = new File(绝对路径);
3、File类_绝对路径和相对路径
1).绝对路径:带盘符的全路径;
2).相对路径:不带盘符的。从项目根目录下找。
4、获取的方法:
getAbsolutePath():返回此File的绝对路径名字符串。
getPath():获取此File对象封装的路径。
getName() :返回由此File表示的文件或目 录的名称。
length():返回由此File表示的“文件”的长度。单位:字节【注意:不能操作目录】
5、判断的方法:
exists():此File表示的文件或目录是否实际存在。
isDirectory():此File表示的是否为目 录。
isFile():此File表示的是否为文件。
6、创建和删除的方法:
createNewFile():如果该名称的文件不存在, 创建一个新的空文件。
delete():可以删除“文件”和“空目录”【非空目录使用递归】。
mkdir():创建单级目录。
mkdirs():创建多级目录。
7、目录的遍历方法:
list() :返回一个String数组,表示该File目录中的所有子文件或目录。
listFiles() :获取此目录下所有的文件/目录的File对象数组。
注意:【listFiles在以下三种情况下会返回null:】
(1)当前的File对象表示的是一个文件。
(2)当前的File对象表示的是一个“系统目录”。
(3)当前的File对象表示的目录不存在。
(4)如果当前File对象指向的是一个存在的空目录,listFile()不返回null,而是一个零长度数组。
2、递归
1、作用、理解:
方法调用其本身;【当前的方法调用当前的方法】
2、注意事项:
1).递归的层次不能太深,否则“栈溢出”。
2).必须要有出口,否则就是“死递归”。
3).构造方法不能递归调用。
3、递归内存溢出隐患的原因:
递归会一直压栈,不弹栈,就会最终导致“栈溢出"。
3、IO流概念
1、介绍:
IO流:可以“读”,“写”文件的内容。
输入流 :把数据 从其他设备上 读取到 内存 中的流。
输出流 :把数据 从内存中写出到 其他设备 上的流。
4、Java的IO体系结构
1、字节流:
1).输入流:InputStream(抽象类)
|--FileInputStream(字节基本流)
|--FilterInputStream(不学)
|--BufferedInputStream(缓冲流)
2).输出流:OutputStream(抽象类)
|--FileOutputStream(字节基本流)
|--FilterOutputStream(不学)
|--BufferedOutputStream(缓冲流)
2、字符流
1).输入流:Reader(抽象类)
|--BufferedReader(缓冲流)
|--InputStreamReader(转换流)
|--FileReader(字符基本流)
2).输出流:Writer(抽象类)
|--BufferedWriter(缓冲流)
|--OutputStreamWriter(转换流)
|--FileWriter(字符基本流)
5、字节流
1、特点:
(1)以字节为单位,读写数据的流。
(2)“字节流”是Java中IO流的最基本的流,任何的其它流都是基于字节流的【例如:字符流、打印流】。
6、字符流
1、特点:
(1)以字符为单位,读写数据的流。
(2)它是java为了解决各个国家使用的编码表不同,字符占用的字节数不同。提供的另一种专门操作纯文本文件的流
7、缓存流
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO 次数,从而提高读写的效率。
8、字符转换流
解决编码格式的一种流。例如:编码使用的GBK,解码使用UTF-8。就会出现乱码的格式。
9、打印流
1).java中有两种打印流:
字节打印流:PrinteStream
字符打印流:printWriter
2).打印流的特点:
1).只有输出流,没有输入流;
2).可以操作控制台,也可以操作文件;
9、常见的字符集
(1)ASCII码表:最早的码表。记录了128个字符,每个字符使用1个字节表示。
(2)中文的码表:【都是以GB开头】
1).GB2312:早期的码表。
2).GBK : 目前使用的码表。里面一共记录了2万多个汉字。
3).GB18030 : 里面有7万多汉字
(3)UTF-8码表:国际码表。
(4)Unicode码表:国际码表。 Java就是支持Unicode码表的。
(5)ISO-8859-1码表:没有中文。
10、序列化
1、序列化:
将一个“对象连同属性值”一起存储在一个文件中。或者通过网络传输,这个过程叫:序列化。
2、反序列化:
指将之前序列化的对象,再次读取到程序中,并在内存中创建对象。
3、一个对象要想序列化,必须满足两个条件:
(1)该类必须实现 Serializable 接口。
(2)该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用 transient 关键字修饰。
4.反序列化
(1)对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个 ClassNotFoundException 异常。
(2)另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操 作也会失败,抛出一个 InvalidClassException 异常。发生这个异常的原因如下:
(1)该类的序列版本号与从流中读取的类描述符的版本号不匹配 。
(2)该类包含未知数据类型。
(3)该类没有可访问的无参数构造方法 。
八、网络编程
1、概述
1、程序的架构:
C/S结构 :全称为Client/Server结构, 是指客户端和服务器结构。 常见程序有QQ、斗地主、网游......
B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。 常见浏览器有谷歌、火狐、等。
2、网络编程的三要素:
(1)IP地址
(2)端口
(3)协议
2、IP地址
1、作用:
指互联网协议地址,俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。
3、端口
1、作用:
网络的通信。是指两个进程之间的通信。端口号的唯一标识符,可以识别设备中的具体进程。端口具体分:两类。
2、物理端口:网卡口。
3、逻辑端口:
(1)由操作系统维护,就是一组数字(唯一标识符)。范围:0--65535。
(2)任何程序在启动时都可以自行申请端口,如果这个端口没被占用,操作系统就可以分配给你的程序使用
(3)注意:
(1)一个程序启动后可以同时占用多个端口。
(2)一个端口在某个时间点上不能被多个程序同时占用
4、协议
1、主要分两类:
网络通信协议、TCP/IP协议。
2、网络通信协议:
通信协议是对计算机必须遵守的规则,只有遵守这些规则,计算机之间才能进行通信。这就 好比在道路中行驶的汽车一定要遵守交通规则一样,协议中对数据的传输格式、传输速率、传输步骤等做了 统一规定,通信双方必须同时遵守,最终完成数据交换。
3、TCP/IP协议:【传输控制协议/因特网互联协议】
它是 Internet最基本、最广泛的协议。定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。它 的内部包含一系列的用于处理数据通信的协议,并采用了4层的分层模型,每一层都呼叫它的下一层所提供的 协议来完成自己的需求。
应用层:HTTP、FTP、TFTP、SMTP、SNMP、DNS。
传输层:TCP、UDP
网络层:ICMP、IGMP、IP、
数据连接层/物理层:由地层网络定义的协议。
5、传输层协议TCP、UDP
1、TCP协议:【传输控制协议 】
(1) TCP协议是面向连接的通信协议即传输数据之前, 在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
(2)连接流程(三次握手,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。)
第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
第三次握手,客户端再次向服务器端发送确认信息,确认连接。
(3)完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可 以保证传输数据的安全,所以应用十分广泛,例如下载文件、浏览网页等。
2、UDP协议:【用户数据报协议】
(1)UDP协议是一个面向无连接的协议。传输数据时,不需要建立连接,不管对方端服务是否启动,直接将数据、数据源和目的地都封装在数据包中,直接发送。
(2)每个数据包的大小限制在64k以内。
(3)它是不可靠协议,因为无连接,所以传输速度快,但是容易丢失数据。
6、TCP通信要求
1、TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。
2、两端通信时步骤:
1. 服务端程序,需要事先启动,等待客户端的连接。
2. 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。
7、Java的TCP通信程序
1、介绍:
在Java中,提供了两个类用于实现TCP通信程序。
2、客户端:
java.net.Socket类表示客户端。创建 Socket 对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。
3、服务端:
java.net.ServerSocket 类表示。创建 ServerSocket 对象,相当于开启一个服务,并等待客户端的连接。
8、Socket类
1、作用:
客户端建立连接服务端
9、ServerSocket
1、作用:
建立一个端口等待连接
10、执行流程
1. 【服务端】启动,创建ServerSocket对象,等待连接。
2. 【客户端】启动,创建Socket对象,请求连接。
3. 【服务端】接收连接,调用accept方法,并返回一个Socket对象。
4. 【客户端】Socket对象,获取OutputStream,向服务端写出数据。
5. 【服务端】Scoket对象,获取InputStream,读取客户端发送的数据。
6. 【服务端】Socket对象,获取OutputStream,向客户端回写数据。
7. 【客户端】Scoket对象,获取InputStream,解析回写数据。
8. 【客户端】释放资源,断开连接。
九、反射
1、概述
1、作用:
“反射”是指“反向加载”要使用的“类”。这种技术可以解决这种类和类之间的依赖关系。
2、注意:
(1)JVM在第一次使用任何类时,都会在内存中创建一个这个类的Class对象。而且针对每个类,都只有这一个Class对象。【理解:JVM启动的时候会把所有的类进行加载到内存中】
(2)Class类:就是Class文件。每一个Class文件都是Class类的一个实例对象。
3、反射工作机制:
(1)首先获取某个类的Class文件。就是让JVM先把这个类Class对象先创建了。
(2)然后JVM加载Class文件。
(3)加载完成Class文件之后,存储到内存中(方法区)。
(4)存储到内存中后,它会直接把Class对象返回给我们的程序。
(5)我们获取到Class对象,就想到于获取到这个对象。
3、特点:
解决类与类之间的耦合。实现高内聚、低耦合的理念。
2、Class对象
1、获取Class对象的三种方式:
1).getClass()方法--Object类中定义的;
2).任何的数据类型(基本类型、引用类型)都有一个静态属性:class
3).Class类的静态方法:forName(全名限定的类名)
注意:三种方式获取的都是同一个Class对象;而且每种方式都是先判断Class对象是否存在,
如果不存在,都会先创建一个Class对象。
2、获取构造方法
getDeclaredConstructor()获取某个构造方法。
getDeclaredConstructors():获取所有的构造方法,包括公有、受保护、默认、私有的。
3、爆力访问:
使用场景:有私有的参数时使用。//由于是私有的构造方法,所以要先设置暴力访问。
setAccessible(true);
4、通过构造方法创建对象:
newInstance();
5、获取成员属性:
getDeclaredField(String fieldName):获取某个成员属性。
getDeclaredFields():获取所有成员属性。
注意:私有的成员属性要先设置暴力访问:对象.setAccessible(true);
6、给成员属性赋值:
set():赋值。
注意:私有先暴力访问。对象.setAccessible(true);
十、注解
1、概述
1、介绍:
注解就是一种“标记”。给编译器(JVM)看到。编译器(JVM)根据注解来完成对应的功能。
2、作用:
用来告诉“编译器”怎样编译“代码”。
3、注解的属性:
(1)可以让用户在使用注解时传递参数。
(2)格式:
格式一:数据类型 属性名();
格式二:数据类型 属性名() default 默认值;
4、特殊属性value
(1)当注解中只有一个属性且名称是value,在使用注解时给value属性赋值可以直接给属性值,无论value是单 值元素还是数组类型。
(2)如果注解中除了value属性还有其他属性,且至少有一个属性没有默认值,则在使用注解给属性赋值时, value属性名不能省略。
5、自定义注解:@interface
(1)格式:
public @interface 注解名{
}
(2)注意事项:
1)这是一个合格的注解。但是它没有任何功能。可以使用在任何地方。
2)如果想要它有功能,需要我们编写“注解解析器”
3)如果只想让这个注解在规定的地方使用。需要元注解。
2、元注解
1、介绍:
(1)元注解是Java API提供的注解。专门用来定义注解的注解。【自定义注解】。它规定了定义的注解可以用在哪些位置,还有注解会存在于哪里。
(2)已经定义好的元注解有两种:
@Target:规定了注解可以用在哪些位置。
@Retention:规定了注解会存在于哪里。
2、@Target:
(1)作用:
(1)它规定了注解可以用在哪些位置。通过它的选择它的属性值来进行规定注解用在那些地方。
(2)它的选择值被定义在java.lang.annotation.ElementType枚举中。
(2)使用:
@Target(ElementType.TYPE):可以用在类,接口中
@Target(ElementType.FIELD):可以用在字段上(成员属性)
@Target(ElementType.METHOD):可以用在方法上
@Target(ElementType.PARAMETER):可以用在参数上
@Target(ElementType.CONSTRUCTOR):可以用在构造方法是哪个
@Target(ElementType.LOCAL_VARIABLE): 用在局部变量上.
3、@Retention:
(1)作用:
(1)它规定了注解会存在于哪里。
(2)它的可选值也被定义在java.lang.annotaion.RetentionPolicy枚举中。
(2)使用:
@Retention(RetentionPolicy.SOURCE):
注解只存在于“源码中”。不会在Class文件中出现。给编译器看的。
@Retention(RetentionPolicy.CLASS):
注解会存在于源码、class中。当JVM运行此类时,不会将注解信息读取到内存。给编译器看的。
@Retention(RetentionPolicy.RUNTIME):
注解会存在于源码、class、内存中。给运行时的“注解解析器”看的。像JUnit的@Test。
3、注解解析器
1、介绍:
就是通过Java技术获取注解数据的过程则叫做注解解析。
2、注解解析的相关接口;
(1)Anontation:所有注解类型的公共接口,类似所有类的父类是Object。
(1)AnnotatedElement:定义了与注解解析相关的方法。
常用方法:
isAnnotationPresent(): 判断当前对象上是否有指定注解,有true,没有false
getAnnotation(); 获得当前对象上指定的注解对象。
getAnnotations(); 获得当前对象及其从父类上继承的所有的注解对象。
3、注解解析器步骤:
//1.反射获取使用了注解的那个类的Class对象。
//2.创建对象。
//3.获取它内部的所有的成员方法。
//4.遍历每个方法。
//5.判断此方法上是否使用的自定义注解。
//6.有就执行此方法。
十一、JUnit单元测试
1、概念
1、作用:
(1)单元测试”是指可以将“一部分” 代码进行单独测试。不用执行所有的代码。
(2)JUnit是一个第三方公司实现的一个“单元测试”的工具包,它是基于“注解”的。
2、常用注解
1、@Test:测试方法。(可以定义多个)
2、@Before:在@Test方法之前运行。(可以定义多个)
3、@After : 在@Test方法之后运行。(可以定义多个)
注意:
测试方法,必须是公有、无参、无返回值,非静态的方法。
4、@BeforeClass : 用于测试静态方法。在所有的注解之前只运行一次。
5、@AfterClass : 用于测试静态方法。在所有的注解之后只运行一次。