想要查看前面的笔记请翻阅我的CSDN博客,作者码字不易,喜欢的话点赞,加个关注吧,后期还有很多干货等着你!
1.基础语法:
注释:
行内注释://
多行注释:/* */
文档注释:/** */
关键字和保留字:
关键字(53个): Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等,关键字不能用作变量名、方法名、类名、包名。
包引入和包声明:import package
用于类的接口声明:class extends implements interface
修饰符:abstract final native private protected public static synchronized transient volatile
数据类型:boolean byte char short int long float double
流程控制:break case continue default for do while if else return switch
创建对象:new
引用:this super
方法返回类型:void
异常处理:catch finally throw throws try
操作符:instanceof
某些数据类型的可先值(非关键字):false true null
关键字 | 含义 |
abstract | 表明类或者成员方法具有抽象属性 |
assert | 断言,用来进行程序调试 |
boolean | 基本数据类型之一,声明布尔类型的关键字 |
break | 提前跳出一个块 |
byte | 基本数据类型之一,字节类型 |
case | 用在switch语句之中,表示其中的一个分支 |
catch | 用在异常处理中,用来捕捉异常 |
char | 基本数据类型之一,字符类型 |
class | 声明一个类 |
const | 保留关键字,没有具体含义 |
continue | 回到一个块的开始处 |
default | 默认,例如,用在switch语句中,表明一个默认的分支。Java8 中也作用于声明接口函数的默认实现 |
do | 用在do-while循环结构中 |
double | 基本数据类型之一,双精度浮点数类型 |
else | 用在条件语句中,表明当条件不成立时的分支 |
enum | 枚举 |
extends | 表明一个类型是另一个类型的子类型。对于类,可以是另一个类或者抽象类;对于接口,可以是另一个接口 |
final | 用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量 |
finally | 用于处理异常情况,用来声明一个基本肯定会被执行到的语句块 |
float | 基本数据类型之一,单精度浮点数类型 |
for | 一种循环结构的引导词 |
goto | 保留关键字,没有具体含义 |
if | 条件语句的引导词 |
implements | 表明一个类实现了给定的接口 |
import | 表明要访问指定的类或包 |
instanceof | 用来测试一个对象是否是指定类型的实例对象 |
int | 基本数据类型之一,整数类型 |
interface | 接口 |
long | 基本数据类型之一,长整数类型 |
native | 用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的 |
new | 用来创建新实例对象 |
package | 包 |
private | 一种访问控制方式:私用模式 |
protected | 一种访问控制方式:保护模式 |
public | 一种访问控制方式:共用模式 |
return | 从成员方法中返回数据 |
short | 基本数据类型之一,短整数类型 |
static | 表明具有静态属性 |
strictfp | 用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范 |
super | 表明当前对象的父类型的引用或者父类型的构造方法 |
switch | 分支语句结构的引导词 |
synchronized | 表明一段代码需要同步执行 |
this | 指向当前实例对象的引用 |
throw | 抛出一个异常 |
throws | 声明在当前定义的成员方法中所有需要抛出的异常 |
transient | 声明不用序列化的成员域 |
try | 尝试一个可能抛出异常的程序块 |
void | 声明当前成员方法没有返回值 |
volatile | 表明两个或者多个变量必须同步地发生变化 |
while | 用在循环结构中 |
数据类型:
基本数据类型:
整数:byte 1 , shrot 2 , int 4(默认) , long 8
浮点数:float 4 , double 8 (默认)
字符:char 2
布尔值:boolean 1位
引用数据类型:类,接口,数组
类型转换:
自动类型转换:低转搞
强制类型转换:高转低
变量和常量:
变量:
作用域:类变量,实例变量,局部变量
常量:final关键字
命名规范:
- 见名知意
- 驼峰命名(变量,方法)
- 类:首字母大写的驼峰命名
- 常量大写+下划线
- 不要使用拼音
运算符:
算数运算符:+,-,*,/,%,++,--
赋值运算符:=
关系运算符:>,<,>=,<=,==,!=,instanceof
逻辑运算符:&&,||,!
位运算符:&,|,^,~,>>,<<,>>>
条件运算符:三元运算:?:
扩展运算符:+=,-=,*=,/=
包机制:
命名规范:域名倒写
作用:防止命名冲突
常用关键字:package,import
2.流程控制
Scanner:
用户交互
顺序结构:
程序默认的结构,自上而下的执行
选择结构:
if 单选择结构
if-else 双选择结构
if-elseif-else 多选择结构
switch case 穿透现象需要使用break终止流程,使用default来确定默认流程
循环控制:
while:先判断后走流程
do....while:先走do流程,再判断
for:最常用的循环
forEach:增强版for循环,循环基本类型的时候还是for循环,循环集合的时候是使用的迭代器作为底层
break&continue&return:
break:跳出循环
continue:终止当次循环
return:结束当前方法
3.方法
方法的定义:
修饰符 返回值 方法名(参数){return 返回值}
方法的调用:
静态:类名.方法名
非静态:对象.方法名
方法重载和重写:
重载:名称相同,参数列表不同
重写:名称相同,参数列表相同,继承后覆盖
命令行传参:
给main传递参数:Jvm传参
可变长参数:
...(必须放在最后一个参数)
递归:
自己调用自己,给自己一个出口
4.数组
数组定义:
类型[](最常用)
{1,2,3,4,1}必须是同一个类型
数组的使用:
通过下标拿到值,出现异常会出现ArrayIndexoutofBounds异常抛出
数组工具类:
Arrays使用
数组排序算法:
冒泡排序,选择排序,插入排序,快速排序,归并排序,希尔排序,堆排序,基数排序;
5.面向对象
类与对象:
类:对象的模板
对象:类的具体实例
构造方法:
构造的重载,一个类可以有多个构造器,类会有默认无参数构造,如果定义了有参数构造,必须再添加一个无参数构造器,如果是单列模式必须构造器私有化。
nwe对象:
栈存放引用,堆存放具体的对象
面向对象的三大特性:
封装:属性私有化,提供对应的get和set
继承:使用extends关键字进行继承操作,所有的类都会集成Obgect类,子类继承后会拥有父类的所有特性,这里引出了方法重写,及子类可以进行方法重写后,将父类的方法覆盖。使用this调用当前实例的方法和访问属性,使用super可以调用父类的方法和访问父类属性,只用继承一个类,但是可以实现多个接口
多态:父类的引用指向子类的对象,instanceof关键字,如果匹配可以进行类型之间的转换
修饰符:
public:公开的
protected:同包下可以使用
private:私有的
static:静态的,与类一同初始化
final:常量标记
abstract:抽象的
接口:
使用interface关键字定义接口,约束只能定义方法名,子类实现接口就必须重写其中的方法,当接口只用一个方法的时候,我们称作函数式接口,可以使用lambda表达式进行简化;
接口&抽象类:接口更加抽象
实现:一个类可以使用implements关键字实现多个接口
内部类:
局部内部类:
静态内部类:
匿名内部类(重点):
6.异常
java异常:
分为Exception和Error:
Exception:
检查型异常(IOException):需要捕获进行处理,如果不做处理编译不通过
运行时异常 (RuntimeException):无需捕获,运行时会自动抛出报错
Error:jvm异常和jwt异常
自定义异常:
class 自定义异常类 extends 异常类型(Exception){
// 因为父类已经把异常信息的操作都完成了,所在子类只要在构造时,将异常信息传递给父类通过super 语句即可。
// 重写 有参 和 无参 构造方法
}
处理异常:
try{}:正常运行的代码块
catch(){}:捕获异常的代码块
finally{}:不管任何情况都会运行的代码块
throw:在方法内部手动抛出异常
throws:在方法开始定义后,向上抛出异常
7.常用类
Object类:
常用方法:hashcode(),toString(),clone(),getClass(),notify(),wait(),equals()
String类:
String的不可变性:创建使用final
StringBuffer&StringBuilder:StringBuffer线程安全,StringBuilder线程不安全。
Math类:
常用的数学运算
File类:
针对文件一些操作类
Date类:
Date:获取时间
SimpleDateFormat:格式化(yyyy-MM-dd HH:mm:ss)
Calendar:建议使用的时间类
Random类:
生成随机数,UUID
包装类:
基本类型进行自动装箱和自动拆箱
8.集合框架
- List(对付顺序的好帮手): List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象
- Set(有意义的性质):不会重复的集合。不会有多个元素引用相同的对象。
- Map(用Key来搜索的专家):使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key无法重复,典型的Key是String类型,但也可以是任何对象。
Collection
List
- Arraylist: Object数组
- Vector: Object数组
- LinkedList: 双向链表(JDK1.6之前为循环链表,JDK1.7取消了循环)
Set
- HashSet(无序,唯一): 基于 HashMap 实现的,底层采用 HashMap 来保存元素
- LinkedHashSet: LinkedHashSet 继承于 HashSet,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 HashMap 实现一样,不过还是有一点点区别的
- TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树)
Map
- HashMap: JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间
- LinkedHashMap: LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。详细可以查看:《LinkedHashMap 源码详细分析(JDK1.8)》
- Hashtable: 数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的
- TreeMap: 红黑树(自平衡的排序二叉树)
泛型:
<>约束类型转换问题
Collections工具类:
封装了常用集合工具
9.IO流
一.流的概念:
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。它的特性是进行数据传输;
例如从水源地长江把水导入自来水厂,然后又从自来水厂把水送到各家各户。从长江到自来水厂之间的管道我们可以称之为输入流,从自来水厂把水送到各家各户的管道我们称之为输出流,我们大概可以这么理解。
二.流的继承体系
在java中,为了对不同来源和性质的流对象调用统一的方法,java中的流首先定义了顶层输入/输出流的接口或抽象类,这样不同性质具体的流对象就会有统一的调用方法以便使用,在使用流对象时,尽量的按照在具体流所实现的接口(抽象类)中定义的方法使用。
三.流的分类
流按照流向数据流向可以分为输入流和输出流。
流按照处理数据类型的单位不同可以分为字节流和字符流。
四.字节流和字符流
字节流:InputStream和OutputStream是java中可以按照最小字节单位读取的流,即每次读写一个字节,字节流是直接连接到输入源的流。
字符流:是以字符为单位进行数据处理的IO流。本质其实就是基于字节流读取时,去查找指定的码表。
字节流与字符流之间的区别:
1.读写单位不同:字节流式以字节(8位2进制)为单位,字符流是以字符为单位,根据码表映射字符,一次可能读多个字节。
2.处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
3.一次读入或读出是8位二进制。
4.字符流:一次读入或读出是16位二进制。
结论:只要是纯文本数据优先使用字符流,除此之外都使用字节流。
五.输入流和输出流的用途
输入流是指程序从数据源中读取数据。只进行读操作;
输出流是指将数据从程序中写到指定的文件中;
六.输入流字节流InputStream与输出字节流InputStream
1.InputStream是一个抽象类,是所有输入字节流的父类。
2.ByteArrayInputStream、StringBufferInputStream、FileInputStream是三中基本的戒指了,他们分别从数组、StringBuffer、和本地文件中读取数据。
3.PipedInputStream
是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
4.ObjectInputStream
和所有FilterInputStream
的子类都是装饰流(装饰器模式的主角)。
1.OutputStream
是所有的输出字节流的父类,它是一个抽象类。
2.ByteArrayOutputStream
、FileOutputStream
是两种基本的介质流,它们分别向Byte 数组
、和本地文件
中写入数据。
3.PipedOutputStream
是向与其它线程共用的管道中写入数据。
4.ObjectOutputStream
和所有FilterOutputStream
的子类都是装饰流。
七.节点流和处理流的概念
节点流:直接与数据相连,进行数据的读写;
处理流:是指在节点流上套接了一层。
常用的节点流
1.文 件 :FileInputStream
、 FileOutputStrean
、FileReader
、FileWriter
文件进行处理的节点流
2.数 组 :ByteArrayInputStream
、 ByteArrayOutputStream
、 CharArrayReader
、CharArrayWriter
对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
3.字符串 :StringReader
、 StringWriter
对字符串进行处理的节点流
4.管 道 :PipedInputStream
、PipedOutputStream
、PipedReader
、PipedWriter
对管道进行处理的节点流
常用的处理流
1.缓冲流:BufferedInputStrean
、BufferedOutputStream
、 BufferedReader
、 BufferedWriter
增加缓冲功能,避免频繁读写硬盘。
2.转换流:InputStreamReader
、OutputStreamReader
实现字节流和字符流之间的转换。
3.数据流: DataInputStream
、DataOutputStream
等-提供将基础数据类型写入到文件中,或者读取出来。
八.转换流
InputStreamReader
、OutputStreamWriter
要InputStream
或OutputStream
作为参数,实现从字节流到字符流的转换。
10.多线程
线程创建方法:
继承Tread:底层调用start0方法,直接交给c去处理,
实现Runnable:函数式接口 使用lambda表达式编写,
Callable:Juc编程
什么是线程,什么是进程?
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如 CPU 时间,内存空间,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。
线程基本状态:
Java 线程在运行的生命周期中的指定时刻只可能处于下面 6 种不同状态的其中一个状态(图源《Java 并发编程艺术》4.1.4 节)。
线程在生命周期中并不是固定处于某一个状态而是随着代码的执行在不同状态之间切换。Java 线程状态变迁如下图所示(图源《Java 并发编程艺术》4.1.4 节):
由上图可以看出:
线程创建之后它将处于 NEW(新建) 状态,调用 start()
方法后开始运行,线程这时候处于 READY(可运行) 状态。可运行状态的线程获得了 cpu 时间片(timeslice)后就处于 RUNNING(运行) 状态。
操作系统隐藏 Java 虚拟机(JVM)中的 READY 和 RUNNING 状态,它只能看到 RUNNABLE 状态(图源:HowToDoInJava:Java Thread Life Cycle and Thread States),所以 Java 系统一般将这两个状态统称为 RUNNABLE(运行中) 状态 。
当线程执行 wait()
方法之后,线程进入 WAITING(等待)状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态,而 TIME_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)
方法或 wait(long millis)
方法可以将 Java 线程置于 TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到 BLOCKED(阻塞) 状态。线程在执行 Runnable 的run()
方法之后将会进入到 TERMINATED(终止) 状态。
静态代理模式:
new Tread(Runnable).start()
线程同步:
解决:多对象操作同资源
前提:队列和锁
使用Synchronized进行加锁:
同步方法:不建议使用,锁太多了
同步代码块:常用,一般是锁this
死锁现象:
条件:互斥,请求与保持,不剥夺条件,循环等待
破坏其中一个条件就会解决死锁
Lock:
Reentrantlock:lock上锁,unlock去锁
线程通信:
缓冲区:消息队列
标志位:红绿灯现象
Synchronized使用wait等待,使用notfyAll唤醒
Reentrantlock使用await等待,使用signalAll唤醒
线程池:
池化思想:防止过大的消耗
基本数据:池大小,连接数,保持时间等等
推荐使用:ThreadPoolExecutor
ThreadPoolExecutor
3 个最重要的参数:
corePoolSize
: 核心线程数线程数定义了最小可以同时运行的线程数量。maximumPoolSize
: 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。workQueue
: 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,信任就会被存放在队列中。
ThreadPoolExecutor
其他常见参数:
keepAliveTime
:当线程池中的线程数量大于corePoolSize
的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了keepAliveTime
才会被回收销毁;unit
:keepAliveTime
参数的时间单位。threadFactory
:executor 创建新线程的时候会用到。handler
:饱和策略。关于饱和策略下面单独介绍一下。
11.注解和反射
注解:
元注解:定义在注解之上
内置注解:java内置注解
自定义注解:自己写或者是第三方提供的注解
反射会去读取注解并完成使用注解
反射:
Class获取:
1. Class.forName(常用)
2. Hero.class
3. new Hero().getClass()
类的加载机制:
相关使用:
Mathod:方法---invoke
Field:属性---get,set,当私有属性时需要设置setAccessible(true)
Construct:构造器---new Instance