JDK
基础
标识符
用来标识代码中的元素,例如类名、方法、字段、变量、包名等等
标识符命名规则
由字母、数组、下划线、$符号组成
不能以数字开头
严格区分大小写
见名知意
不能是关键字
关键字
被Java语言赋予了特定的意义,一共50个关键字、2个保留字
关键字表
注释
单行注释
以 // 开头
多行注释
以 /* 开头 */ 结尾
文档注释
以/** 开头 */结尾 用来注释类和方法,通过注释来记录类或者方法的信息
变量
用来存放数据,但数据的值可以改动
变量的使用方式
int age = 10;
变量类型 变量名 = 变量值 ;
变量的注意事项
变量名是一个合法标识符
变量名不可以使用Java的关键字
变量名不可以重复
局部变量
定义在方法里或者局部代码中
必须手动初始化来分配内存,必须赋值
作用在方法或局部代码块执行完,就内存就释放局部变量
成员变量
定义在类里方法外
不手动初始化,也会自动初始化成默认值
作用在整个类中,随着类释放
常量
用来存放数据,但是数据的值是固定的
常量的创建方式
final int age = 10
fianl修饰符 常量类型 常量名 = 常量值
注意事项与变量一样,只是被final关键字修饰
类型
基本类型
基本类型速查表
基本类型转换关系
类型转换
小转大 隐式转换
大转小 显式转换
小转大直接转,大转小强制转,浮点转整数小数没
包装类型
自动装箱
基本类型 到 包装类型的过程
自动拆箱
包装类型 到 基本类型的过程
BigDecimal
数字包装类型 抽象父类Number
基本类型与包装类型
基本类型与包装类型对应关系
基本类型没有任何功能只是一个变量
包装类型可以有丰富的功能
BigDecimal 解决浮点数运算不精确的问题
Add(BigDecimal bd) : 做加法运算
Subtract(BigDecimal bd) : 做减法运算
Multiply(BigDecimal bd) : 做乘法运算
Divide(BigDecimal bd) : 做除法运算,除不尽时会抛异常
Divide(BigDecimal bd,保留位数,舍入方式) : 除不尽时使用
setScale(保留位数,舍入方式) : 同上
pow(int n) : 求数据的几次幂
舍入方式
ROUND_UP 直接进位,不算0.1还是0.9,都进位
ROUND_DOWN 直接舍弃,不算0.1还是0.9,都舍弃
ROUND_CEILING(天花板) 向上取整,取实际值的大值
运算符
运算速查表
分支结构
if
switch
循环结构
for
嵌套for
while
do while
数组
创建方式
int a[] = new int[5]
int a[] = new int[]{1,2,3}
int a[] = {1,2,3}
int[] a = new int[5]
int[] a = {1,2,3,4,5}
int[] a = new int[]{1,2,3,4,5}
数组工具类 Arrays
Arrays.toString(数组) //把数组里的数据用逗号连接成一个字符串
Arrays.sort(数组) //对数组进行排序
Arrays.copyOf(数组,新的长度)
把数组赋值成一个指定长度的新数组
新数组的长度 大于 原数组 相当于复制并增加位置
新数组的长度 小于 原数组 相当于截取一部分数据
二维数组
创建方式
int[][] a= {{3,5},{7,9},{1,2}}
面向对象
重载/重写
重载
一个类中有多个同名的方法但是方法的参数列表不同
方便外界进行调用,什么样的参数程序都可以找到对应的方法来执行,体现程序的灵活性
重写
@Override 修改父类的功能
要求 两同两小一大
方法名与参数列表相同
子类的返回值类型小于等于父类的返回值类型
子类的抛出异常类型小于等于父类的抛出异常类型
子类的权限修饰符大于等于父类的权限修饰符
在不修改源码的前提下,进行功能的修改和拓展
异常
继承结构
Throwable 顶级父类
Error 系统错误,不可修复
Exception 可以修复的错误
RunTimeException
ClassCastExecption
ClassNotFoundException
异常解决方案
向上抛出
throws关键字
对于异常不进行解决,由谁调用谁负责解决
捕获处理
try catch finaly
try中存放可能会出现异常的代码
catch 处理异常的方案
finally必须会执行的代码
正则表达式
字符串格式规则,用来判断输入的内容是否符合要求
正则表达式速查表
String
Matches(正则) 当前字符串是否匹配正则表达式
replaceAll(正则,字串) 替换子串
split(正则) 拆分字符串
面向对象编程的三大特征
封装
优点
提高安全性
提高重用性
private 关键字,权限修饰符用来修饰成员变量和成员方法,被私有化的成员只能在本类中访问,可以对外提供get/set方法供外界调用
权限修饰符速查表
继承
特点
使用extents关键字来表示继承关系
相当于子类把父类的功能复制了一份
Java只支持单继承,继承具有传递性
不能继承父类的私有成员
继承多用于功能的修改,子类可以使用父类的功能的同时进行功能拓展
super
表示父类的一个引用对象
位置 在构造方法中且必须是第一行
重写
多态
前提
继承
方法重写
父类引用 指向 子类对象 用父类的类型 干活的是子类对象
优点
提高程序的扩展性 和 可维护性
向上造型
父类引用指向子类对象
向下造型
为了使用子类特有的方法
规定
多态对象不能使用子类特有的方法
多态对象使用的成员变量是父类的
多态对象使用时使用的资源时父类的
多态对象在使用方法时,如果子类重写了,使用的是子类的方法体
类、接口、抽象
类与对象
对象
三个特点
状态 用来描述对象的基本特征
行为 用来描述对象的功能
标识 用来区分不同的对象,也就是在内存中的唯一地址值
匿名对象
没有名字的对象 new 对象();
适合只使用一次的场景,可以避免多个对象浪费内存
类
Java语言的最基本单位就是类,似于类型
一类事物的抽象,模板或者设计图纸
内部类
内部类可以直接访问外部类中的成员,包括私有成员
外部类要访问内部类的成员,必须要建立内部类的对象
在成员位置的内部类是成员内部类
在局部位置的内部类是局部内部类
类是一类事物的抽象,对象是具体的实现
成员变量描述事物的属性,方法用来描述事物的行为
接口
Interface
对外暴漏的规则,一套开发规范
特点
通过interface 关键字定义接口
通过implements 关键字让子类实现
接口中全部都是抽象方法
突破Java单继承的局限性
接口与类可以多实现,接口与接口可以多继承
提供程序拓展,减低耦合
抽象
abstract
抽象类
被abstract修饰的类叫做
一个类含有抽象方法,那么一定是抽象类
子类继承抽象类
继续抽象,作为抽象子类
重写抽象类中的抽象方法
定义
可以定义成员变量
可以定义成员常量
抽象方法 抽象类中方法只能声明,没有方法体
抽象类不可以被实例化,一般用于多态
抽象类可以有抽象方法也可以有普通方法
抽象类不能与某些关键字一起使用
private 私有化后,子类无法重写,违背抽象思想
static 静态优先于对象存在,存在加载顺序问题
final 无法重写,违背抽象思想
关系
类与类
继承关系,只支持点继承
类与接口
实现关系,可以单实现也可以多实现
接口与接口
继承关系,可以单继承也可以多继承
抽象与类
继承实现关系,通过extends 继承,实现类实现抽象类定义的抽象方法
抽象与接口区别
抽象类中可以有抽象方法或者普通方法,而接口只有抽象方法没有普通方法
接口的方法会自动拼接成 public abstract 变量会自动拼接成 public final static
抽象类可以有构造方法,用来给子类创建对象,接口中没有构造方法
抽象类和接口都不能实例化
抽象方法只能声明不能实现,接口是设计的结果,抽象类是重构的结果
栈、队列
栈
队列
代码块
局部代码块
位置 方法里的代码
作用 用于控制变量的作用范围
变量的作用范围越小越好
构造代码块
位置 构造方法里的代码
作用 用于抽取构造方法中的共性代码
执行时机 调用构造方法
构造代码块优先于构造方法加载
静态代码块
随着类的加载而加载,且只加载一次,一般用于初始化
位置 类里方法外
被static修饰
三种代码块的比较
静态代码块
随着类的加载而加载,且只加载一次,一般用于初始化
构造代码块
创建对象时自动调用每次创建对象都会被调用,用于提取构造共性
局部代码块
方法里的代码块,限制局部变量的范围
方法
构造方法
与类同名且没有返回值的方法
用来完成对象的创建或者初始化
当类实例化对象时,就会自动调用构造方法
关键字
static
用于修饰成员(成员变量与成员方法)
随着类的加载而加载,也随着类的释放在释放,且只加载一次
静态资源也叫类资源,全局唯一,被全局所有对象共享
可以直接使用类名调用
静态只能调用静态,非静态可以直接调用静态
final
修饰类、方法、成员变量
类不能被继承
方法不能被重写
常量不能被改变
当父类不允许子类改变时,可以使用final关键字来修饰父类
作用 被final修饰过就是最终形态,不允许其他人改动
this关键字
代表本类对象的一个引用对象
当成员变量与局部变量重名时,使用this可以指定成员变量
流
IO
流的分类
方向
输入流 input
输出流 output
类型
字节流
字符流
文件流
根据路径可以执行一次操作
可以封装文件路径,文件夹路径,不存在的路径
File 方法速查表
复合
字节输入流 InputStream
FileinputStream
直接插在文件上,直接读取文件数据
FileInputStream(File file)—直接传文件对象
BufferedInputStream
字节输入缓冲流
嵌套字节输入流,提高效率
BufferedInputStream(InputStream in)
ObjectInputStream
字节输出流 OutputStream
FileOutputStream
直接插在文件上,直接写出文件数据
构造方法(创建对象):
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的文件输出流
FileOutStream(File file) 创建一个向指定File对象表示的文件中写入数据的文件输出流
FileOutStream(File file,boolean append)—如果第二个参数为true,表示追加,不覆盖
创建一个向指定File对象表示的文件中写入数据的文件输出流,后面的参数是指是否覆盖原文件内容
BufferedOutputStream
该类实现缓冲的输出流,通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必每次针对字节写出调用底层系统
BufferedOutputStream(OutputStream out)
ObjectOutputStream
字符输入流 Reader
FileReader
用来读取字符文件的便捷类
FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader
FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader
BufferedReader
字符输入缓冲流
InputStreamReader
字符输出流 Writer
FileWriter
用来写入字符文件的便捷类,此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的.如果需要自己自定义这些值,可以先在FileOutputStream上构造一个OutputStreamWriter.
FileWriter(String filename) 构造方法(创建对象):
FileWriter(String filename,boolean append) 根据给定的文件名以及指示是否附加写入数据的boolean值来构造FileWriter
BufferedWriter
将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组和字符串的高效写入.可以指定缓冲区的大小,或者接受默认的大小,在大多数情况下,默认值就足够大了
BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流
OutputStreamWriter
PrintWriter一行行写出
数据只能从头到尾顺序读写一次
序列化与反序列化
概述
序列化是指将对象的状态信息转换为可以存储或传输形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后可以通过从存储区中读取或者反序列化对象的状态,重新创建该对象.
序列化:利用ObjectOutputStream,把对象的信息,按照固定的格式转成一串字节值输出并持久保存到磁盘
反序列化:利用ObjectInputStream,读取磁盘中之前序列化好的数据,重新恢复成对象
应用场景
需要序列化的文件必须实现Serializable接口,用来启用序列化功能
不需要序列化的数据可以修饰成static,原因:static资源属于类资源,不随着对象被序列化输出
每一个被序列化的文件都有一个唯一的id,如果没有添加此id,编译器会自动根据类的定义信息计算产生一个
在反序列化时,如果和序列化的版本号不一致,无法完成反序列化
常用与服务器之间的数据传输,序列化成文件,反序列化读取数据
常用使用套接字流在主机之间传递对象
不需要序列化的数据也可以被修饰成transient(临时的),只在程序运行期间在内存中存在,不会被序列化持久保存
ObjectOutputStream
ObjectOutputStream 将 Java 对象的基本数据类型写入 OutputStream,通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象
writeObject(Object obj) 将指定的对象写入 ObjectOutputStream
ObjectInputStream
ObjectInputStream对以前使用ObjectOutputStream写入的基本数据和对象进行反序列化重构对象。
readObject() 从 ObjectInputStream 读取对象
我们在反序列化时,JVM会拿着反序列化流中的serialVersionUID与序列化时相应的实体类中的serialVersionUID来比较,如果不一致,就无法正常反序列化,出现序列化版本不一致的异常InvalidClassException。
集合
用来存放数据的容器,相比起数组,集合长度可变,使用更加灵活,集合的英文名称是Collection,是用来存放对象的数据结构,而且长度可变,可以存放不同类型的对象,并且还提供了一组操作成批对象的方法.Collection接口层次结构 中的根接口,接口不能直接使用,但是该接口提供了添加元素/删除元素/管理元素的父接口公共方法.
分类
Conllection
List
数据有下标,有序,可重复
ArrayList
内部是数组结构,封装数组的操作,每个元素都有下标
内部数组初始容量为10,如果不够会以1.5倍的容量进行增长
查询快,增删满
LinkedList
底层是链表结构
查询慢,增删快
常用方法
List方法速查表
Set
数据无下标,无序,不可重复
HashSet
底层是哈希表,包装了HashMap
TreeSet
底层是TreeMap,也是红黑树的形式,便于查找数据
常用方法速查表
Map
Key Value结构
分类
HashMap
Key需要重写
hashCode() 用来判断Hash值是否相同,重写后根据属性判断
equlas() 判断属性的值是否相等,重写后根据属性判断
底层是Entry[]数组,根据hash算法来计算数据的存放位置
算法:hash(key)%n , n就是数组的长度,其实也就是集合的容量
当计算的位置没有数据的时候,会直接存放数据
当计算的位置,有数据时,会发生hash冲突/hash碰撞,解决的办法就是采用链表的结构,在数组中指定位置处已有元素之后插入新的元素,也就是说数组中的元素都是最早加入的节点
TreeMap
根据Key值获取Value值
Key值不允许重复,如果重复Key值会被覆盖
存放无序的数据
初始容量是16,使用到75%后会进行扩容
常用方法
关系图
集合中引用了泛型的概念
进程
概念
进程是指正在运行的程序,表示程序所占用的内存区域
特点
独立性
晋城市系统中独立存在的实体,拥有自己独立的资源,每个进程都拥有自己私有的地址空间,没有进程本身允许的情况下,一个进程不可以直接访问其他进程的地址空间
动态性
进程与程序的区别在于,程序是一个静态的指令集合,而进程是一个正在系统中活动的指令集和,程序加入时间的概念以后称为进程,具有自己生命周期和不同的状态
并发性
多个进程可以在单个CPU并发执行,多个进程之间不会互相影响
并行与并发
线程
线程是操作系统可以进行运算调度的最小单位,包含在进程中是进程的实际运作单位,一个进程开启开启多个线程,其中有一个主线程来调用本进程的其他线程
多线程的特点
CPU分时调度
时间片,即CPU分配给各个线程的一个时间段,称作它的时间片,即该线程被允许运行的时间,如果在时间片用完时线程还在执行,那CPU将被剥夺并分配给另一个线程,将当前线程挂起,如果线程在时间片用完之前阻塞或结束,则CPU当即进行切换,从而避免CPU资源浪费,当再次切换到之前挂起的线程,恢复现场,继续执行
线程的五态
新建状态(New) : 当线程对象创建后就进入了新建状态.如:Thread t = new MyThread();
就绪状态(Runnable):当调用线程对象的start()方法,线程即为进入就绪状态,已经做好准备等待CPU进行调度
运行状态(Running):当CPU调度了处于就绪状态的线程时,此线程才是真正的执行,即进入到运行状态
阻塞状态(Blocked):处于运状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入就绪状态才有机会被CPU选中再次执行.
等待阻塞:运行状态中的线程执行wait()方法,本线程进入到等待阻塞状态
同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),它会进入同步阻塞状态
其他阻塞:调用线程的sleep()或者join()或发出了I/O请求时,线程会进入到阻塞状态.当sleep()状态
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期
常用方法
线程池
ExecutorService/Executors
同步锁
synchronized 解决线程安全问题
语法
线程安全问题的前提 在多线程程序中,有共享资源,且多条语句操作共享资源
同步与异步
同步 排队的效果,同一时刻只能由一个线程独占资源
异步 抢占资源,线程之间互相抢占资源
锁分类
悲观锁和乐观锁
乐观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态 乐观锁认为竞争不总是会发生,因此它不需要持有锁,将”比较-替换”这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。
悲观锁:像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态. 悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像synchronized,不管三七二十一,直接上了锁就操作资源了。
Synchronized 互斥锁(悲观锁,有罪假设)
采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁。
每个对象都有一个monitor(锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池。任何一个对象系统都会为其创建一个互斥锁,这个锁是为了分配给线程的,防止打断原子操作。每个对象的锁只能分配给一个线程,因此叫做互斥锁。
ReentrantLock 排他锁(悲观锁,有罪假设)
ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,实际上独占锁是一种相对比较保守的锁策略,在这种情况下任何“读/读”、“读/写”、“写/写”操作都不能同时发生,这在一定程度上降低了吞吐量。然而读操作之间不存在数据竞争问题,如果”读/读”操作能够以共享锁的方式进行,那会进一步提升性能。
ReentrantReadWriteLock 读写锁(乐观锁,无罪假设)
因此引入了ReentrantReadWriteLock,顾名思义,ReentrantReadWriteLock是Reentrant(可重入)Read(读)Write(写)Lock(锁),我们下面称它为读写锁。
读写锁内部又分为读锁和写锁,读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。
读锁和写锁分离从而提升程序性能,读写锁主要应用于读多写少的场景
内部类
内部类的定义
成员内部类 : 类里方法外
局部内部类:类里方法里
匿名内部类:没有名字的
调用内部类中的方法
1、修饰符 public 的情况
通过外部类.内部类 a = new 外部类().new 内部类();
2、修饰符是 private的情况
外部类中创建一个方法来new内部类,然后再调用内部类对象.方法
3、修饰符是 static 的情况
通过外部类.内部类 a = new 外部类().new 内部类();
4、匿名内部类 不用起名字
new 类名 { };
泛型
<?>
用来约束类型,给程序员看到,程序编译后会被删除
用于接口 类 方法
常用名称
反射
运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。
使用
获取字节码对象
Class.forName(“类的全路径”);
类名.class
对象.getClass();
暴力反射
Declared
注解
JDK注解
@Override :用来标识重写方法
@Deprecated标记就表明这个方法已经过时了,但我就要用,别提示我过期
@SuppressWarnings(“deprecation”) 忽略警告
@SafeVarargs jdk1.7出现,堆污染,不常用
@FunctionallInterface jdk1.8出现,配合函数式编程拉姆达表达式,不常用
元注解
@Target 注解用在哪里:类上、方法上、属性上等等
ElementType.TYPE 应用于类的元素
ElementType.METHOD 应用于方法级
ElementType.FIELD 应用于字段或属性(成员变量)
ElementType.ANNOTATION_TYPE 应用于注释类型
ElementType.CONSTRUCTOR 应用于构造函数
ElementType.LOCAL_VARIABLE 应用于局部变量
ElementType.PACKAGE 应用于包声明
ElementType.PARAMETER 应用于方法的参数
@Retention 注解的生命周期:源文件中、字节码文件中、运行中
@Inherited 允许子注解继承
@Documented 生成javadoc时会包含注解,不常用
@Repeatable注解为可重复类型注解,可以在同一个地方多次使用,不常用
自定义注解
@interface 注解名{}
方法体中可以定义属性age int age() default 0