Java知识点总结
2021-05-17 18:53:21 145 举报
AI智能生成
Java是一种广泛使用的面向对象编程语言,具有跨平台、安全性高、易于维护等特点。其核心知识点包括数据类型、运算符、流程控制、数组、字符串处理、类和对象、继承和多态、接口和抽象类、异常处理等。此外,Java还提供了丰富的标准库,如集合框架、输入输出流、网络编程等。Java的语法规范严谨,对代码格式有严格要求,有助于编写高质量的代码。掌握Java编程,可以为开发各类应用提供基础,如桌面应用、移动应用、Web应用等。
作者其他创作
大纲/内容
数据类型
数据类型的转换
强制转换
int自动转long
int自动转float
int自动转double
float自动转double
long自动转float
long自动转double
自动转换
特例
基本数据类型
byte
short
int
十进制数在内存中以补码形式存在
long
Date时间的数据类型底层是long类型
char
char c = '\u1234';
char c = 2 + '2';,那么c=4
编译成功,单引号中只能是四位数字,不能多也不能少
float
double
boolean
引用数据类型
类
接口
数组
流程控制语句
分支语句
if-else
switch-case
支持可以自动转int的类型
支持String类型
JDK1.7版本及以后支持
支持枚举
循环语句
for
while
do-while
foreach
底层就是迭代器
循环关键字
break
continue
return
标识符
标识符定义
类名
变量名
方法名
等等统称
标识符规则
不能数字开头
不能含空格
不可有特殊符号
标识符组成
数字
字母
下划线
$
运算符
算数运算符
比较运算符
逻辑运算符
三目运算符
拓展运算符
赋值运算符
位运算符
<<
>>
&
|
~
^
>>>
数组
声明与初始化
特点
长度不可变
存放类型一定
操作
复制
扩容
剪切
遍历
相关问题
排序
查找
求值
变量
成员变量
定义在类全局
有默认值
数字默认为0
引用类型默认为null
布尔默认false
系统不会给final修饰的成员变量初始化
局部变量
仅在该代码块可用
无默认值
系统不会对局部变量初始化
构造方法
方法名
返回值
不用写返回值类型
返回值为该类的对象
不写返回值不是没有返回值
参数列表
无参
有参
重载
方法名相同
参数列表不同
new调用该方法创建对象
构造方法必须调用父类构造方法
方法
参数的传递
值传递(call by value)
址传递(call by reference)
方法重载
确定方法的三要素
调用者
方法名
形参列表
形参个数可变的方法
方法三要素
返回值类型
方法名
参数列表
方法所属性
类方法
属于该类本身
不经过对象
普通方法
属于该类对象
方法默认主调者
静态方法默认由类直接调用
普通方法由该类对象默认调用
抽象方法
默认由public abstract修饰
只有方法签名,没有方法体
不可被调用
必须被重写,重写规则在本思维导图的面向对象三大特征的继承中
抽象
抽象类
包含元素
可以包含普通方法和抽象方法
成员变量
初始化块
内部类
含有构造器,但是不是用来实例化对象的,是用来供给子类调用的
特点
用abstract关键字修饰类
抽象类不可被实例化
抽象类不可被private和protected修饰
抽象类可以继承抽象类
抽象类可以实现接口
主要作为多各类的模板
abstract
static和abstract不能同时修饰方法
final和abstract不能同时修饰方法
接口
接口定义
接口是比抽象类更抽象的类
不再使用class关键字,而是使用interface
定义多个类应该遵守的规范
不可被实例化
不能被final和protected修饰修饰
一个类可以实现多个接口
接口可以多继承接口
接口中元素
接口不包含构造方法
接口中只能定义静态常量,不可定义普通成员变量
接口中不能声明引用
Java7
成员变量只能是静态常量
抽象方法
Java8新特性
可以在接口中定义默认方法
可以在接口中定义静态方法
Java9新特性
可以在接口中写私有方法
可以在接口中写私有静态方法
static
只能修饰属性、方法和初始化块
由它修饰的属性和方法属于类本身,不属于对象
由它修饰的属性或方法,该类所有对象共享,在内存中仅有一份
static修饰的在类加载时就初始化了
static修饰的可以直接用类名调用
不能使用this
静态代码块在类加载时初始化,并且只加载一次
final
可以修饰普通类、方法和属性
用final修饰的变量不可被二次赋值
用final修饰的类不可被继承
final修饰的方法不可被重写
重写final修饰的方法会发生编译错误
final修饰的成员变量必须指定初始值
由final修饰的类变量
final修饰的实例变量
final修饰的成员变量不允许在显式初始化前直接访问,但允许通过方法访问
修饰局部变量
final修饰引用变量
该变量不可被二次赋值
该变量引用指向的对象的内部可以发生改变
宏变量
被final修饰
在编译时,初始值就被确定
只有在定义该变量时指定其初始值才有宏变量的效果
初始化块
顺序
前面定义的块先执行
后面定义的块后执行
先执行静态后执行普通
可包含
局部变量
调用其它对象的方法
控制语句
静态初始化块
只能被static修饰
类加载时执行
普通初始化块
创建对象时执行
枚举
枚举的本质是用enum修饰的final类
抽象与非抽象
非抽象枚举类默认由final修饰但不能显示使用final修饰该类
抽象枚举类不能用final修饰,并且默认用abstract修饰且不能显示使用abstract修饰该类
枚举类里实现抽象方法,每个枚举值分别实现抽象方法,语法与匿名内部类大致相似
枚举也是一个类,在编译后,也会生成.class文件,枚举是一个特殊的类
枚举类可以实现多个接口
如果按照普通类实现接口那样,重写接口中的方法,那么枚举类中所有实例的行为就会相同
枚举类实现接口,应该让每个枚举值分别实现接口中的方法
这样写实质上是写的枚举的匿名内部子类,在编译时也会生成匿名子类的.class文件
包含元素
成员变量
枚举值
方法
构造器
与普通类的区别
构造器只能用private修饰
默认继承java.lang.Enum抽象类
默认使用final修饰不能被继承
枚举类的所有实例在第一行列出,并且默认用public static final修饰
枚举不可以显示继承任何类
Enum提供的方法
values()
获取枚举类的所有实例,返回一个该类类型的数组
该方法为静态方法
该方法是在编译期做的事情,在api中没有介绍
toString()
实例方法
返回枚举常量名称
正是由于这个方法,所以可以直接输出枚举类型的常量名
String name()
返回枚举实例名称
与toString方法功能相同
异常
异常的定义及概念
异常是用来处理可能因很多原因出现的以外状况的
异常的五个关键字
try
这个块中写可能发生异常类代码
与catch搭配使用
如果try中某一行代码发生异常,那么此后的代码将不执行
catch()
这个块中写发生异常后的处理方法
传一个异常类型的参数
一个try后可以跟多个catch,当发生异常时根据参数找catch块
finally
在try-catch最后
一般在这个块中关闭在try块中打开的资源
如果try中有return,那么会先执行finally中的语句,最后return
不管有没有异常,这个块中的程序都会执行,除非整个程序结束
不要在此块中使用return、throw关键字,一旦使用,try块和catch块中的rerturn和throw将失效
throws
写在方法签名处,向调用该方法的上级抛异常,声明抛出异常的类
后面跟异常类
throw
抛出一个具体的异常,是一个独立的语句,后面跟异常的一个对象
Java非正常情况有两种
错误(Error)
此错误无法处理,发生的可能性小,所以不需要处理机制
发生场景
系统崩溃
内存溢出
动态连接失败
异常(Exception)
可处理异常
发生场景
异常的分类
编译时异常
Checked异常
该类异常在编译阶段必须被处理,否则编译错误
运行时异常
Runtime异常
该异常在编译时无需处理
Throwable
Error
AWTError
IOError
LinkageError
ThreadDeath
Exception
RuntimeException
NullPointerException
IndexOutOfBoundsExceptipn
StringIndexOutOfBoundsException
ArraysIndexOfBoundsException
ClassCastException
IllegalArgumentException
ArithmeticException
NumberFormatException
IOException
SQLException
处理异常的方式
try-catch-finally
异常处理可以嵌套,但会降低执行效率不建议使用
try块catch块遇到return、throw都会结束,然后直接奔向finally
Java7新增多异常捕获
捕获多异常时,异常变量有final隐式修饰
throws
只能在方法签名中使用
后面跟异常类
可以抛出多个异常类,用,隔开
一旦是使用了抛出异常,就不能继续捕获异常,只能由调用者捕获或者继续上抛
throw自行抛出异常
直接抛出一个异常的实例,可以当作独立语句使用
在catch块中结合throw使用
所有异常类的通用方法
getMessage()
获取异常详细信息的字符串,包括发生异常的原因和位置
System.out.print(e.getMessage())
printStackTrace()
打印异常错误和位置以及异常跟踪栈信息
getStackTrace()
返回跟踪异常栈信息
自定义异常
继承异常类,然后根据异常的处理方式抛出异常
IO
路径
反斜线\
在双引号中为\\
绝对路径
优点:在任何项目中使用绝对路径绝没问题
缺点:没有系统移植性
相对路径
File
特点
File可以创建删除重命名文件和目录(目录就是文件夹)
File不可以访问文件本身的内容
常用方法
exists()判断文件或目录是否存在
isFile()判断File对象对应的是否是文件而不是目录
isDirectory()判断对象是否是目录而不是文件
createFile()
delete()删除对象对应的文件或空路径,如果想要产出一个文件夹下所有东西,
包括这个文件夹下的目录文件与子目录及其文件,可以使用递归,如左侧代码
包括这个文件夹下的目录文件与子目录及其文件,可以使用递归,如左侧代码
mkdir()创建目录,但需要有父目录
mkdirs()创建目录不需要父目录存在
getName()以字符串形式返回文件或目录名
list()
获取路径下所有子目录和文件的名,返回String数组
listFile()
获取File对应的路径下的目录和文件的全路径,返回File数组
过滤器
FileFilter
方法accept(File pathname)
accept的参数市listFile方法传递过来的
在accept方法中,进行判断,如果满足自己要求,则将true返回给listFile方法,此时listFile将
此时拿到的全路径保存到File数组中
此时拿到的全路径保存到File数组中
若拿到的路径不满足自己的要求,则返回给listFile方法false,此时不保存该路径
listFile(FileFilter接口实现类)
该方法在获取到文件全路径的同时,会去调用过滤器的accept方法,并将全路径作为参数传给accept方法
遍历多级目录需要使用递归
流的分类
按方向
输入流
只能从中读取数据而不能写
输出流
只能向其写数据而不能读
按功能
字节流
操作的数据单元是8位的字节
主要由InputStream和OutPutStream作为基类
字符流
操作的数据单元是16位的字符
主要有Reader和Writer作为基类
字符流可以将字符串作为物理节点
对象流
按角色
节点流
低级流
程序直接与数据源连接
处理流(也称包装流)
高级流
程序与数据源不直接连接,通过处理流包装已存在的流进行数据处理
IO的四十多个类的抽象基类
所有输入流基类
InputStream
方法
int read()
读取一个字节数据,返回这个字节数据的十进制整数值
int read(byte[] b)
读取一组字节数据并放入byte类型的数组中
返回读取的字节数
int read(byte[] b, int off, int len)
读取一组字节数据放入byte数组中
从off开始
读取len个字节放入数组
返回读取的字节数
FileInputStream->InputStream
Reader
方法
int read()
读取一个字符数据返回这个字符的int值
int read(char[] c)
读取一组字符并放入char类型的数组中
返回读取的字符数
int read(char[] c, int off, int len)
读取一组字符放入char类型的数组中
从off开始
读取len个字符
返回读取的字字符数
FileReader->InputStreamReader->Reader
流的关闭
void close()
保证流的物理资源被收回
保证缓冲当中的数据flush到数据节点即输出目标中
所有输出流基类
OutputStream
write(int c)
将指定的字节输出到流中
void write(byte[] b)
将指定字节数组输出到指定流
void write(byte[] b, int off, int len)
将指定字节数组输出到流
从off开始
输出len个字节
FileOutputStream继承自OutputStream
Writer
write(int c)
将指定的字符输出到流中
void write(byte[] b)
将指定字符数组输出到指定流
void write(byte[] b, int off, int len)
将指定字符数组输出到流
从off开始
输出len个字节
void write(String s)
将字符串输出到指定流
void write(String s,int off, int len)
将制定字符串输出到指定流
从字符串的off开始输出
输出len个字符
FileWriter->OutputStreamWriter->Writer
处理流
特点
只要构造器中传的不是物理节点而是一个已有的节点流,那这个流一定是处理流
处理流的关闭只需要将最开始定义的处理流关闭即可,系统会自动关闭被该处理流包装的节点流
常见处理流
打印流
特点
次流不负责数据源,只负责数据目的
为其他流添加功能
永远不会抛出IOException,但会抛出别的异常
两个打印流的方法是一致的
PrintStream
PrintWriter
转换流
InputStreamReader
参数传字节输入流
将字节输入流转换为字符输入流
该类父类为Reader
OutputStreamWriter
参数为字节输出流
将字节输出流转换为字符输出流
该父类为Writer
BufferedReader
字符输入流
功能更强大
主要优点
提供readLine()方法每次读一行
继承自Reader
BufferedWriter
字符输出流
带缓冲
newLine()写入一个换行符
继承自Writer
序列化
序列化的目的
序列化的意义
使得对象可以脱离程序的运行而独立存在
什么是序列化
对象的序列化指将一个Java对象写入IO流
方法不会被序列化,序列化的仅仅是数据
对象的反序列化是从IO流中恢复Java对象
如何实现可序列化
实现Serializable接口
实现该接口不需要实现任何方法
实现Externalizable接口
对象流实现序列化
首先该对象的类实现可序列化接口
静态不是对象的一部分所以不参与序列化
序列化步骤
1.创建ObjectOutputStream,该输出流是一个处理流
2.调用该处理流的writeObject()方法输出可序列化对象
当一个可序列化类有多个父类时,(包括直接父类和间接父类),这些父类要么有无参构造器,要么是可序列化的
否则在反序列化时将抛出InvalidClassException异常,如果父类不是可序列化的,只是带有无参构造器,那么在
序列化时,父类中定义的成员变量的值不会序列化到二进制流中
否则在反序列化时将抛出InvalidClassException异常,如果父类不是可序列化的,只是带有无参构造器,那么在
序列化时,父类中定义的成员变量的值不会序列化到二进制流中
反序列化
1.创建ObjectInputStream流,该流同样是处理流
2.调用处理流的readObject()方法读取流中的对象,如果知道对象的类型,可以强转
反序列化读取的是Java对象的数据而不是Java类,因此采用反序列化恢复对象时必须提供Java对象所属的class文件
如果找不到,则发生类找不到异常。另外,反序列化无须调用构造函数来初始化Java对象。
如果找不到,则发生类找不到异常。另外,反序列化无须调用构造函数来初始化Java对象。
使用序列化机制向文件写入多个Java对象,使用反序列化恢复对象时必须按照写入顺序进行读取
反序列化对象时,不会调用该对象的构造函数,但如果该对象所属类有父类,且父类是不可序列化的,则会调用父类无参构造函数
如果父类是可序列化的,则不会调用
如果父类是可序列化的,则不会调用
对象引用序列化
当一个类中的成员变量是一个引用类型,那这个引用类型必须是可序列化的,否则,不管你实现还是
不实现Serializable接口,你的类都不可以实现序列化
不实现Serializable接口,你的类都不可以实现序列化
特殊序列化机制
1.所有保存到磁盘的对象都有一个序列化编号
2.当程序试图序列化一个对象时,程序将先检查该对象是否已被序列化,只有该对象从未被序列化的时候,才会被序列化
3.如果对象已经被序列化过,那么程序将只是输出一个序列化编号,而不是再次重新序列化该对象
**当反序列化两次一个对象时,他们返回的对象用==判断则返回true
注意
当程序序列化一个可变对象时,只有第一次使用writeObject()方法输出时才会将该对象转换成字节序列并输出,
当程序第二次调用方法输出,程序只是输出前面序列化编号,即使后面对象实例变量值已经改变,改变的实例变量也不会
被输出
当程序第二次调用方法输出,程序只是输出前面序列化编号,即使后面对象实例变量值已经改变,改变的实例变量也不会
被输出
自定义序列化
递归序列化
序列化一个对象,若它的成员变量引用到另一个对象,那也会序列化引用到的对象
引用到的对象的成员变量又引用到另一个对象,则也会序列化这个对象
引用到的对象的成员变量又引用到另一个对象,则也会序列化这个对象
transient
只能修饰实例变量
作用是让序列化忽略该实例变量
该变量称为瞬态实例变量
特殊签名的方法
readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
writeObject(ObjectOutputStream out) throws IOException
序列化注意事项
对象的类名、实例变量(包括基本类型、数组和对其他独享的引用)都会被序列化;方法、类变量,transient都不会被序列化
实现Serializable接口的类如果需要让某个实例变量不被序列化,用transient关键字,而不是static,虽然static可实现此效果,但不合理
保证序列化对象的成员变量类型也是可序列化的,否则使用transient关键字,不然这个类不可序列化
反序列化对象时必须有序列化对象的class文件
当通过文件、网络来读取序列化对象时,必须按照实际写入顺序读取
序列号冲突问题
在编辑器将java文件编译成class文件的同时,如果这个类可序列化,则给这个类计算序列号,第一次序列化该类
对象时,按照该序列号为准,当序列化以后改变了类的内容,则编辑器重新编译且生成新序列号,此时再反序列化
则会出现序列号冲突,反序列化异常
对象时,按照该序列号为准,当序列化以后改变了类的内容,则编辑器重新编译且生成新序列号,此时再反序列化
则会出现序列号冲突,反序列化异常
给该可序列化类定义序列号:格式要求static final long serialVersionUID = 222L
NIO
线程
线程的本质
线程本质上是进程中一段并发操作的代码,所以线程需要操作系统投入CPU资源来运行和调度
线程和进程
进程
一个程序进入内存运行时,就变为一个进程
进程是操作系统进行资源分配和调度的一个独立单位
进程的三个特征
独立性
是系统中独立存在的
拥有自己私有的地址空间
拥有自己独立的资源
动态性
进程拥有自己的生命周期和各种状态
并发性
多个进程可以在单个处理器上并发执行,各个进程之间不会相互影响
并发性与并行性
并发性是同一时刻一条指令在单个处理器上执行,由于处理器快速轮换,就好像多条指令同时执行
并行性是同一时刻多条指令在多个处理器上同时执行
线程
当一个程序运行时,内部包含多个顺序执行流,每个顺序执行流就是一个线程
线程是进程的基本单位
每个进程包含一个或多个线程
同一个进程内的线程独立运行但资源共享
线程的创建方式
继承Thread类
1.定义Thread的子类并重写run()方法,该方法就是线程执行体
2.创建Thread子类的实例,该实例就是线程对象
3.用该实例调用start()方法就启动了一个线程
实现Runnable接口
1.定义Runnable接口的实现类,并重写run()方法,该方法就是线程执行体
2.创建实现类的实例,并以此实例作为Thread的target来创建Thread对象
3.用Thread对象调用start()方法启动线程
使用Callable和Future创建
Callabe接口
call()方法
Callable接口提供了call()方法作为线程执行体,该方法可以有返回值
该方法可以声明抛出异常
该接口不是继承自Runnabl接口,所以不可作为Thread的target
Callable有泛型限制,且泛型与call方法的返回值类型一致,Callable是函数式接口,可以用lambda表达式表示
Future接口
提供一个FutureTask实现类,该类实现了Future、Runnable接口,可以作为Thread的target
让FutureTask与Callable关联,来代表Callable接口中call()方法的返回值,并作为Thread的target
提供的方法
cancel()
get()
isDone()
isCancelled()
创建线程步骤
1.创建Callable接口的实现类并实现call()方法,该方法作为线程执行体
2.使用FutureTask类来包装Callable对象,该FutureTask对象封装了call()方法的返回值
3.使用FutureTask对象作为Thread对象的target创建并启动线程
4.调用FutureTask对象的get()方法来获得返回值
线程的状态
新建状态
new一个线程类
只由JVM给其分配内存空间,初始化其成员变量
就绪状态
当一个新建线程调用start()方法,该线程由新建状态变为就绪状态
运行状态
当就绪状态的新线程获得cpu,该线程变为运行状态
阻塞状态
当运行状态的线程遇到IO请求或者调用sleep()方法,线程变为阻塞状态
线程在等待某个通知(notify)
程序调用了线程的suspend()挂起方法,该方法容易导致死锁
死亡状态
线程执行体执行完成正常结束变为死亡状态
线程调用stop()方法,线程变为死亡状态
线程的控制
join线程
join()
后台线程
setDaemon(true)可以将前台线程设置为后台线程
isDaemon()判断线程是否为后台线程
当前台线程全部死亡,后台线程也会直接死亡
线程睡眠
sleep(int 毫秒)
改变线程优先级
setPriority(int priority)
getPriority()
线程同步
线程安全问题
同步代码块
把对共享资源的操作的代码放在同步代码块中,使其任何时刻只能有一个线程访问该代码块
语法格式
synchronized(obj){....}
volatile关键字
只能修饰成员变量
可以称之为轻量级synchronized
两大性
可见性
即一个线程将其改变,其他线程立马可以知道
有序性
指程序中上下两条无关的代码执行不会被指令重排序
指令重排序是指在运行程序时,处理器为了优化性能,代码的执行顺序可能不会按代码的顺序执行
同步方法
用synchronized关键字修饰方法
原子性
可见性
有序性
同步锁lock
创建锁对象
每次只能有一个线程对Lock对象加锁,访问共享对象之前应先获得Lock对象
悲观锁
对应现实生活中悲观的人,即什么事都想的比较坏。在进行数据访问的时候,总是想着一定会有人来争抢资源,所以悲观
锁是在用之前就上锁。数据库中的行锁,表锁等,读锁、写锁等都属于悲观锁,另外synchronized锁和Lock锁都是悲观锁机制
锁是在用之前就上锁。数据库中的行锁,表锁等,读锁、写锁等都属于悲观锁,另外synchronized锁和Lock锁都是悲观锁机制
适用场景
悲观锁适用于多写的应用场景,多写的场景发生线程冲突的情况较多,适合适用之前就加锁
乐观锁
对应于现实生活中乐观的人,即把什么事都想得比较好,在进行数据访问的时候,总是认为没有人访问,所以乐观锁是在使用
数据的时候不会上锁,而是在最后更新的时候通过版本号机制或CAS算法判断有没有其他线程更新,再决定是否驳回操作
数据的时候不会上锁,而是在最后更新的时候通过版本号机制或CAS算法判断有没有其他线程更新,再决定是否驳回操作
适用场景
乐观锁适用于多读应用程序,在这种多读情景下,线程发生冲突较少,适合使用前不加锁
版本号机制
数据库每张表都有一个版本号,每次更新版本号都会加1,在读数据库的时候,也会读取该表的版本号,当对表中数据做更新
的时候,会检查此刻的版本号跟起初读的版本号是否一致,如果不一致,将驳回本次更新操作
的时候,会检查此刻的版本号跟起初读的版本号是否一致,如果不一致,将驳回本次更新操作
CAS算法
无锁算法,所以又叫非阻塞同步
线程通信
Object类提供了三个控制线程的方法,该方法由线程同步监视器调用
wait()
notify()
notifyAll()
Condition接口下的方法控制线程通信
获取Codition的实例
API
await()
singal()
singalAll()
线程其他相关类
ThreadLocal
代表线程局部变量,在共享对象内部创建一个ThreadLocal类型的待泛型的成员变量即可
API
set(T value)
设置线程副本的值
get()
获取线程变量副本的值
remove()
删除此线程局部变量中当前线程的值
入口
main方法
命名规范
变量
驼峰命名
首字母小写
项目名
全小写
包名
全小写
域名倒置
常量
全大写
用下划线连接
类
首字母大写
驼峰命名
类和对象
类的定义
一般用public修饰
一个类只能有一个公共类
基本的类包含属性和方法
对象的创建
new关键字
创建对象时根据构造器对对象成员变量进行初始化
对象的引用
对象赋给引用变量
引用变量存对象的地址
this
构造器中this指向正在初始化的对象
方法中,this指向调用该方法的对象
在静态方法中不可使用this
必须写在构造器第一行
类中元素
成员变量
方法
初始化块
构造方法
内部类
接口
枚举
内部类
特征
内部类更好的封装隐藏,不允许同包下其他类访问
内部类可以直接访问外部类私有数据,反之不行
匿名内部类适用于创建仅需使用一次的类
分类
成员内部类
将一个类定义在另一个类的类中
成员内部类可以无条件访问外部类数据,外部类需要创建内部类对象,通过对象访问
若内部类与外部类发生重名,则这些数据在内部类将被隐藏
不可包含静态属性和方法
局部内部类
局部内部类存在于方法中。和成员内部类的区别:局部内部类的访问权限仅限于方法或作用域内
局部内部类只能访问外部类的final变量
不能由权限修饰符和static修饰
匿名内部类
没有构造方法
只能访问外部类的final变量
传参如果是一个接口,可以直接在方法括号内创建接口的匿名内部实现类
静态内部类
由static修饰的内部类
不可访问外部类的非静态变量和方法
静态内部类不可包含非静态成员
不同点
权限修饰符
private
protected
static
默认
public
非静态内部类不能拥有静态成员
非静态内部类不可以拥有静态初始化块,可以拥有普通初始化块
内部类实例的创建
外部类.内部类 对象名 = new 外部类.内部类();
外部类.内部类 对象名 = 外部类对象名.new 内部类();
面向对象三大特征
封装
本质
隐藏具体细节,实现模块化编程
类和类之间的关系
泛化关系
继承
实现
依赖关系
例如人类拧螺丝方法,需要依赖工具类的实例
关联关系
若A与B有关联,说明AB两个类有关系,他们两个并不能共同构成一个整体,
例如人类和车有关联,但人类和车类并不能组合起来构成一个更大的整体
但妻子丈夫儿女有关联且能构成一个家庭,这叫聚合
例如人类和车有关联,但人类和车类并不能组合起来构成一个更大的整体
但妻子丈夫儿女有关联且能构成一个家庭,这叫聚合
聚合关系
聚合关系是建立在关联关系之上的,两个类是聚合关系那么一定相关联,反之则否
弱聚合
通常把弱聚合称为聚合
若AB弱聚合关系,则AB可以共同构成更大的整体,但AB不用同时出现,例如丈夫妻子和儿子,当儿子不出现的时候,丈夫和妻子
也为一个家庭,而后可以出现不同个儿子共同构成家庭,
也为一个家庭,而后可以出现不同个儿子共同构成家庭,
强聚合
通常把强聚合称为组合
若两个类具有强聚合关系,则一个类在实例化时就必须把另一个类实例化,例如选择题类和选项类,在一道选择题
被实例化的同时需要实例化n个选项,即两个类必须同时出现
被实例化的同时需要实例化n个选项,即两个类必须同时出现
继承
extends关键字
子类获得父类全部成全变量和方法,但仅部分可被公开访问
子类可获得父类静态方法
子类可获得父类静态属性
java中只可单继承
继承抽象类必须重写抽象类中的所有抽象方法
重写
重写父类方法将覆盖父类方法
子类对象不可调用被覆盖方法
子类中可以调用被覆盖方法
实例方法用关键字super调用
类方法用类名调用
@Override
注解
只能标注方法
重写规则
重写权限修饰符不能变小
重写必须方法名一致参数列表一致,返回值类型可不同
不能重写私有方法
用private修饰的方法对子类隐藏,无法构成重写
super
用于限定该对象调用他从父类继承到的东西
与this一样,不可在静态方法中使用
调用父类构造器
子类成员变量与父类成员变量类型一样名一样,则会隐藏父类成员变量
父类设计规则
尽量隐藏父类内部数据
不让子类随意访问、修改父类方法
成员变量都用private修饰
不被访问的方法可以用private修饰
不想被重写但让子类访问的方法可以用public final修饰
希望某方法被子类访问和重写但不希望其他类自由访问可以用protect修饰
尽量不在构造器中使用将被重写的方法
继承和组合的使用
继承的两个类之间是"是"的关系
组合两个类之间是"有"的关系
类只能单继承类,但接口可以多继承接口,类可以多实现接口
多态
分类
编译时类型
运行时类型
成员变量不存在多态,多态只可能发生在行为上
多态存在的必要条件
存在继承关系
存在重写
存在父类引用指向子类对象
向下转型
父类向子类转需要强转
强转后释放子类的拓展属性和方法
向上转型
子类可以自动转换 为父类
转换成父类以后将隐藏子类的拓展属性和方法
设计模式
高内聚低耦合
内聚是描述模块内的功能联系,一个好的内聚模块应当恰好做好一件事
耦合描述的是各个模块间的联系,耦合度是指模块间的依赖关系(调用关系、控制关系、数据传递关系)
模块间关系越多,耦合程度就越强,在面向对象思想领域,要求低耦合
模块间关系越多,耦合程度就越强,在面向对象思想领域,要求低耦合
各个设计模式图解
链接地址
创建型设计模式
工厂模式三兄弟
反例设计
将创建许多对象的职责全部交给一个类,用户只需要在创建这个类的时候传相应参数
就可以得到想要的对象
就可以得到想要的对象
缺点
里面存在大量的条件判断语句,比较影响程序性能
违背单一职责原则
违背开闭原则
高耦合
重复代码较多
简单工厂模式
设计思想
将需要创建的各个对象的代码封装成各个类,将这些类共同的代码封装成抽象类做他们的父类
再提供一个工厂类并提供用于创建所需要的各个对象的方法
客户端只需要调用工厂类的方法并传入相应参数便可以得到想要的对象
简单工厂模式的定义
定义一个工厂类,它可以根据参数的不同返回不同的实例,这些实例通常有一个共同父类;
内置静态方法,专门用于获取实例,因此又叫静态工厂方法模式
内置静态方法,专门用于获取实例,因此又叫静态工厂方法模式
简化
将工厂类与抽象父类合并,也就是在抽象父类中定义用于创建各个对象的静态方法
优点
实现了对象的创建与使用分离
通过改变参数就可以获取不同对象,比较灵活
缺点
工厂类职责过于繁重
引入工厂类,增加了类的个数,并提高代码理解难度和复杂度
当增加新的产品类,则必须修改工厂类内部代码,违背了开闭原则
适用场景
工厂类负责创建的对象较少
客户端只知道创建对象所需参数,对如何创建对象并不关心
工厂模式
设计思想
针对不对的具体产品类,提供不同的工厂类
工厂模式的定义
定义一个用于创建对象的接口,让子类决定将哪一个类实例化
工厂模式让一个类的实例化延迟到其子类,由创建对象的工厂的各个子类决定创建哪个实例
角色
Product(抽象产品)
ConcreteProduct(具体产品)
Factory(抽象工厂)
ConcreteFactory(具体工厂)
优点
客户端无需知道具体对象的创建细节
基于工厂角色和产品角色的多态性设计是工厂模式的关键
完全符合开闭原则
缺点
在出现新的需要创建的对象时,系统中的类会成对增加
适用场景
客户端不需要知道要创建的对象类,只需要知道该类对应的工厂类即可
抽象工厂类通过其子类来指定创建哪个对象
抽象工厂模式
针对属于同类的产品提供不同的工厂类,即一个工厂类负责生产一族产品
抽象工厂的定义
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类
包含角色
AbstractFactory(抽象工厂)
它声明了一组用于创建一族产品的方法,每一个方法对应一 种产品。
ConcreteFactory(具体工厂)
它实现了在抽象工厂中声明的创建产品的方法,生成一组具 体产品
这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
AbstractProduct(抽象产品)
它为每种产品声明接口,在抽象产品中声明了产品所具有的 业务方法。
ConcreteProduct(具体产品)
它定义具体工厂生产的具体产品对象,实现抽象产品接口中 声明的业务方法。
开闭原则倾斜
增加产品族完全符合开闭原则
产品族指的是一组产品例如海尔公司的冰箱空调洗衣机
增加产品等级结构
产品等级结构指的是一个公司,例如增加一个电视
优点
增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产 品族中的对象。
缺点
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,
这显然会带来较大的不便,违背了“开闭原则”。
这显然会带来较大的不便,违背了“开闭原则”。
单例模式
目的
确保该类只能创建一次对象,即确保对象的唯一性
单例模式出现动机
1.如果需要创建的很多个对象他们的内容都一样,那就没必要创建很多个,只用一个就好,可以避免系统资源浪费
2.如果一个系统需要的某一个类的对象每次的内容都是相等的,那每次实例化这个类不可能保证每次都相等,为了使某个类
每次创建的对象都完全一样,就需要单例模式
每次创建的对象都完全一样,就需要单例模式
定义
确保一个类只有一个实例
自行实例化并向整个系统提供这个实例
设计方式
将该类构造器设为私有
在该类中定义并保存该类的唯一实例
定义静态方法,供外部访问该类的唯一静态实例
角色
Singleton(单例)
在单例类内部,只生成一个实例,同时提供一个getInstance()静态工厂方法,供外部访问该唯一实例
为防止外部对该类实例化,需要将其构造方法进行私有化,在类内部定义了一个Singleton类型的静态对象,
作为外部共享的唯一实例
为防止外部对该类实例化,需要将其构造方法进行私有化,在类内部定义了一个Singleton类型的静态对象,
作为外部共享的唯一实例
分类
饿汉式单例
在定义静态变量的时候实例化该类
这样不会出现并发问题
懒汉式单例
在调用静态工厂方法时判断单例是否为空,如果为空创建,不为空则直接返回
但在多线程环境中还是会出现多个实例的情况
在静态工厂方法上加synchronized关键字,使其每次只能被一个线程访问
原型模式
目的
为了解决每次需要创建与之前对象内容基本相同但又不是同一个对象的问题,
Sunny公司针对员工写重复的工作周报问题提出了原型设计模式,即对象的克隆
Sunny公司针对员工写重复的工作周报问题提出了原型设计模式,即对象的克隆
定义
先创建一个原型对象,再通过复制创建出更多同类型的对象
角色
Prototype(抽象原型类)
声明克隆方法的接口,是所有具体原型类的父类
ConcretePrototype(具体原型类)
实现抽象原型类,定义原型对象的成员变量即其他方法,并实现克隆方法,用来复制对象
Client(客户类)
在客户端类中创建原型类对象然后调用原型类对象的克隆方法创建出新的相同对象
实现
可以自定义抽象原型类并声明克隆方法然后再自己实现该方法
Object充当抽象原型类,此时只能实现原型对象的浅拷贝,即该对象内部的引用类型无法拷贝出两份
可以定义具体原型类并实现Cloneable接口,在该方法中覆盖Object的clone方法并用super调用父类clone方法
可以定义具体原型类并实现Cloneable接口,在该方法中覆盖Object的clone方法并用super调用父类clone方法
clone方法满足
对任何对象x,都有x.clone() != x
对任何对象x,都有x.clone().getClass() == x.getClass(),即克隆对象与原型对象的类型一 样
如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
建造者模式
结构型模式
适配器模式
桥接模式
组合模式
装饰者模式
外观模式
代理模式
亨元模式
行为型模式
命令模式
迭代器模式
中介者模式
访问者模式
观察者模式
策略模式
状态模式
解释器模式
备忘录模式
模板方法模式
职责链模式
权限修饰符
public
整个项目可用
protected
包内可用
包外子类可用
默认
包内
private
本类
java常用包及类
lang
String
Math
System
arraycopy
Thread
使用lang包中的类不用使用import导包,系统自动导入
util
工具类
Arrays
copyOf
toString
binarySearch()
List
Set
net
网络编程有关
io
输入输出流
text
格式化相关类
sql
JDBC相关类
swing
图形用户界面
awt
图形用户界面
字符串
String
String常用方法
indexOf
返回int下标
传字符或字符串
查找第一次出现的字符的位置
split
返回字符串
传入字符串
按指定字符分割字符串
codePointAt
返回整型
传整型下标
将指定位置字符转换成Unicode码
valueOf
返回字符串
传入八种数据类型+Object
将传入的转换为字符串
getByte
返回byte[]
不传参
按默认编码集将指定字符串转换成字节码
charAt
返回char
传int下标
按照下标取字符
startWith
返回boolean
传int,int
判断该字符串是否以指定字符串开始
endWith
返回boolean
传int,int
判断是否以指定字符串结束
substring
返回string
传int,int
截取字符串
equals
返回boolean
传字符串
判断字符串是否相等
equalsIgnoreCase
返回boolean
传字符串
忽略大小写比较字符串
isEmpty
返回boolean
不传参
判断字符串是否为空字符串
lastIndexOf
返回int
传String引用变量
判断字符串最后一次出现指定子字符串的下标
contains
返回boolean
传CharSequence(String的父类)
判断字符串是否包含指定字符串
concat
返回String
传String
将两个字符串连接
length
返回int
不传参
返回字符串长度
trim
返回String
不传参
删除字符串两端空格
compareTo
返回int
传String
比较两个字符串在字典中的位置
为什么设计成final的
常量池需要
虚拟机对字符串是有优化的,有字符串常量池
如果字符串可以改来改去,那字符串常量将没有意义
缓存hash值
安全性
Java对Stirng的特殊支持
+、+=用于字符串拼接
加号操作一定出现新的String对象
“asa”可以直接创建一个字符串对象
jvm对String拼接的优化
String底层是有final修饰的char数组
该字符串长度不可变,只要是改变字符串的值,一定是new一个新的字符串对象
可变字符串
StringBuilder
底层是没有final修饰的char数组
利用数组复制实现可变字符串
常用方法
substring
字符串截取
该方法是StringBuilder父类的方法
该方法与String的substring方法类似
append
传8种数据类型
返回StringBuilder
字符串拼接
delete
insert(int offset, String str)
构造方法
初始容量为16个字符
StringBulider类型可以直接输出
StringBuffer
跟StringBuilder本质一样
主要区别是StringBuilder多了线程安全
包装类
Integer
valueOf
返回值Integer
传入int,String类型(必须是数字字符串)
将传入的转换成Integer类型
parseInt
返回值int
传String
将特定字符串转换为int
Integer类中有缓存区,其本质是在类中放一个静态一维数组
Byte
Short
Long
Float
Double
Boolean
Charact
valueOf
不可变类
用final和private修饰类的成员变量
提供有参构造方法给成员变量初始化
只提供getter方法
必要时提供hashCode和equals
java.lang.String和八个包装类均为不可变类
不可变类的实例变量不可被改变,可以缓存实例,下次直接拿来用,不必再创建对象
enum类通常应该被设计成不可变类,使其成员变量不允许改变
泛型
集合
Collections
java.util包下的提供了大量操作集合的方法的工具类
排序操作
查找替换操作
Collection
List
ArrayList
底层是Object类型的可变的数组
利用数组的拷贝来进行对容器内数据的操作
特点
有序
有下标
元素允许重复
在查找与修改某个位置的值时效率较高,元素多时在某个位置插入值时效率较低
常用方法
add()
add(E)
set(int,E)
addAll()
addAll(Collection<> c)批量插入
addAll(int index, Collection<> c)批量插入
set()
set(E)
set(int,E)
get(int)
remove(int index)
Vector
与ArrayList一样
只是比ArrayList多了线程安全,效率较低,已成为丢弃容器
Stack子类
栈
后进先出
API
push入栈
pop出栈
peek查看栈顶元素
empty判断是否为空
size元素个数
固定长度的list
调用Arrays的asList方法可将一个数组或指定个数的对象转为List
他是Arrays类中的内部类ArrayList的实例
只能遍历访问该集合元素,不可增删该
LinkedList
底层是数据结构中的双向链表
利用节点的前后指向将一个个节点连接起来组成链
特点
有序
伪下标(,利用循环一直.next就可以找到对应的节点)
元素允许重复
在插入时效率较高,元素多的时候查找效率低
常用方法
linkLast(E e)
linkFirst(E e)
add(E)默认在链表最后查入
addAll()
addAll(Collection<> c)批量插入
addAll(int index, Collection<> c)批量插入
clear()
get()
set(int,E)
add(int,E)
Collection接口方法
add(Object)
addAll(Collection)
clear()
contains(Obj)
containsAll(Collection)
iterator
remove(Obj)
removeAll(Collection)
size()
toArray()
Collection和Collections
Collection接口是List、Set、Queue的父接口,实现了Iterable接口,提供了可以操作上述三个集合的方法。
Collections是一个操作Set、List、Map等集合的工具类
Set
HashSet
特点
按Hash算法来存储集合中的元素,查找插入超级快
无序
不支持排序
不是同步的,线程安全有问题
集合的元素可以为null
HashSet两个元素相等的标准是通过equals返回true并且哈希值相等
LinkedHashSet子类
也是根据哈希值存放
有序
内部多了一个LinkedLish列表用来记录元素插入顺序
性能略低
子主题
当存入可变对象时,如果修改集合对象的内部成员变量,有可能使该对象与集合中其他对象相等,从而导致集合无法准确操作元素
SortedSet
TreeSet
直接父类是SortedSet(继承Set接口)
特点
元素有序
支持排序
元素不可重复
不可有null元素
常用方法
first()
取第一个元素
last()
取最后一个元素
lower()
取指定元素的前一个元素
higher()
取指定元素的后一个元素
截取自TreeSet的方法
headSet(Object)
返回小于指定元素的子集
tailSet(Object)
返回大于指定元素的子集
subSet(o1,o2)
返回在传入参数之间的子集
如果向集合插入可变对象,并且后面程序修改了该对象实例变量,这会导致其顺序发生改变,但集合不会重新调整顺序,甚至会出现重复元素
自然排序
TreeSet会调用集合元素的compareTo(Object)方法比较元素大小进行升序排列
Comparable是一个接口,提供了比较大小的标准
如果试图把一个对象添加到TreeSet时必须实现Comparable接口并实现比较的方法
定制排序
Comparator是一个函数式接口,里面包含compare(o1,o2)方法,比较并返回整数
在创建TreeSet对象时传入一个Comparator对象,可以写匿名内部类,也可以用Lambda表达式代替
Queue
特点
序列
先进先出FIFO
队列不允许随机访问队列中的元素
Deque接口
ArrayDeque实现类
特点
底层基于Array
双端队列
允许从队列两端操作队列
API
addFirst(Object e)
addLast(Object e)
getLast()
getFirst
removeLast
removeFirst()
API
add(Object e)
向队尾添加元素
offer(Object e)
向队尾添加元素
当使用容量有限的队列时,此方法比add更好
element()
获取队列头部元素但不删除
peek()
获取队列头部元素但不删除
poll()
获取并删除队列头部元素
remove()
获取并删除队列头部元素
遍历
普通for循环
foreach循环(底层还是迭代器)
迭代器
先将容器中元素放入迭代器,再根据下面两个方法遍历
hasNext()判断是否还有数据
next()返回元素
Map集合
HashMap
特点
键值对
采用哈希算法,查找非常快
key可以存null
value可以重复
无序
不支持排序
HashMap中是用链地址法来解决哈希冲突的
遍历
forEach
Set<Map.Entry<T,E>>
HashMap集合的元素存入后实际被包装成一个Entry对象,即键值对对象,HashMap提供了一个获得所有Entry对象并放入Set集合的方法
方法
put(T,E)
get(key)
keySet()返回所有key存入set集合
replace(key, value)
clear()
SortedMap接口
TreeMap实现类
特点
有序
支持排序
不可存null
查找较慢
value可以重复
采用红黑树排序
自然排序
按照元素的实际大小
定制排序
调用传Comparator类型的构造方法(在这直接传匿名内部类,并重写comparator方法)
HashTable
线程安全
key,value都不可为null
子类
Properties
特点
不可写泛型
键值都是String
可以和IO结合使用,实现永久存储
API
setProperty(k,v)
getProperty(k)
stringPropertyNames()
类似于Map集合中的keySet方法
特有方法
读到集合
load(InputStream in)
load(Reader r)
写到properties文件
store(OutputStream)
store(Write)
java.util.concurrent
ConcurrentHashMap
底层原理
锁分段技术
首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问
其中一个段数据的时候,其他段的数据也能被其他线程访问。
其中一个段数据的时候,其他段的数据也能被其他线程访问。
Iterator和ListIterator的区别?
网络编程
网络通信协议
TCP/IP协议
应用最为广泛的协议
包括TCP和IP协议
IP地址
计算机在网络中的唯一标识
端口号
程序在电脑中的唯一标识,范围在0~65535,0~1024由计算机软件占用
InetAddress
static InetAddress getByName() 通过主机名获取IP地址
static InetAddress getLocalHost() 获取本机IP地址
String getHostName() 获取主机名
String getHostAddress() 获取主机IP地址对象
传输协议
UDP
无连接通信协议
特点
发送端和接收端不会建立逻辑连接:当一台计算机向另一台计算机发送数据的时候不会去管接收端是否存在
就会发送数据,而接收端接收完数据也不会给发送端反馈
就会发送数据,而接收端接收完数据也不会给发送端反馈
资源消耗小、通信效率高
容易造成数据丢失
有传输大小限制,数据限制在64k以内
适用场景
新闻联播
视频会议
微信聊天、发短信
TCP
面向连接通信协议
三次握手
客户端向服务器端发送连接请求,等待服务器确认
服务器向客户端回送一个响应,通知客户端收到了连接请求
客户端再次向服务器端发送确认信息,确认连接
特点
资源消耗相对较大,通信效率较低
传输大小理论没有限制
比较安全,不会造成数据丢失
适用
资源下载
文件传输
UDP通信
DatagramPacket
数据报包,用于封装数据
DatagramSocket
用于发送和接收数据包的
发送步骤
创建DatagramPacket对象,封装数据,接收端IP和端口
new DatagramPacket(byte[] b, int length, InetAddress address, int port)
创建DatagramSocket对象
new DatagramSoket()
调用DatagramSocket对象的send方法,发送数据包
关闭资源
接收步骤
创建DatagramSocket对象,绑定端口号,要求和发送数据的端口号一致
new DatagramSocket(int port)
创建字节数组用来接收数据
创建数据包DatagramPacket对象
调用DatagramSocket对象的,receive方法
receive(DatagramPacket dp) 接收数据,数据放在数据包中
拆包
发送的IP地址
接收到的字节个数
发送方的端口号(无意义)
关闭资源
TCP通信
面向连接,服务器先开机,客户端连服务器
ServerSocket
用于服务器端
使用构造方法接收客户端连接请求,传端口号,与客户端一致
new ServerSocket(int port)
使用ServerSocket对象的accept方法获取客户端Socket对象
server.accept()
调用客户端Socket对象获取字节输入流,读入客户端发来的数据
socket.getInputStream()
调用客户端Socket对象获取字节输出流,向客户端写数据
socket.getOutputStream()
Socket
用于客户端
客户端使用构造方法与服务器进行连接,如果连接失败则抛异常
new Socket(String IP, int port)
用客户端Socket对象获取输出流,向客户端写数据
socket.getOutputStream()
用客户端Socket对象获取输入流,读服务器发来的数据
socket.InputStream()
多线程上传图片思想:服务器没接收到一个客户端Socket,就给它开启一个线程,并将Socket对象传过去
IP地址
计算机在网络中的唯一标识
0 条评论
下一页