导图社区 Java
Java的思维导图,如静态嵌套类 被声明为静态的内部类 可以不依赖外部类实例就被实例化 内部类:需要在外部类实例化后才能实例化。
编辑于2023-06-09 18:38:24 北京市Java学习
JAVASE基础
面向对象特性:封装 多态(运行时动态绑定) 继承 抽象
权限修饰符 public private protected
new 和clone的区别:new 是根据对象开辟新的空间然后赋值 clone() 方法执行的是浅拷贝操作。新对象与原始对象共享相同的引用,即它们指向相同的对象。因此,在对原始对象进行修改时,新对象也会受到影响。 深拷贝:创建一个新对象并复制原始对象中的所有字段值,可以在类中实现 Cloneable 接口,并重写 clone() 方法,手动处理每个字段的拷贝操作 实现序列化和反序列化可以深度克隆
equals() true 则两个对象有相同的hashCode 反之不一定 自反性 传递性 一致性 对称性
String final类 不可被继承 可以使用关联和依赖 !不是基本数据类型 底层用[]byte实现 String 是不可变类 每次修改都会建立新的对象 并修改引用位置 String + 创建StringBuilder对象 可以使用StringBuffer 可以修改 线程安全 效率略低 StringBuilder 可修改 单线程使用 效率更高 没有同步保护
函数传递对象是 值传递
重载(编译时多态)和重写(运行时多态) 重载参数列表不同 重写 子类重写父类 参数和返回类型一致 final static 构造都不能被重写 访问权限不比父类低,异常不能比父类大(广泛)
抽象类和接口 一个类只能实现一个抽象类 可以实现多个接口 抽象类有构造器 接口没 有 抽象类可以有具体方法 接口没有 接口全public 抽象类可以设置权限 抽象类可以有静态方法 接口没有 接口成员变量都是常量 抽象类可以有成员变量 相同:
静态变量和实例变量
==和equals()区别 ==基本数据类型比数值 引用数据类型比地址 equals()比对象内容 不能比基本类型
异常 编译时异常CheckException( Java独有 try catch/throw) 运行时异常 Error 虚拟机异常,建议终止 Exception可以被处理的异常
throw/throws throw 方法内 抛出异常实例 throws方法后面 声明抛出异常,表示可能性 不一定发生
final finally finalize(Object的一个方法 垃圾回收调用对象时调用此方法)
时间 java.time包 定时器 Timer
装箱和拆箱 Integer -128到127内不会new新的对象,会引用常量池
IO 输入流/输出流 结点流/处理流 字节流/字符流(每次读取两个字节)
序列化 实现Serializable接口 将对象的内容流化 解决对对象流的读写问题
集合 [HashMap HashSetArrayList] 线程不安全 不允许重复键 允许空值和空键 [HashTable(线程安全 键值都不允许空) Vector,ConcurrentHashMap(分16个段存储)、ConcurrentLinkedQueue、ConcurrentLinkedDeque] 线程安全 ArrayList Object[]数组实现
数组和链表Arratlist LinkedList 连续内存大小 查找和增删 空间确定与否 优缺点
多线程 1传统 Thread类编写run()代码 2.传递给Thread对象的自己的Thread对象实例Runnable编写代码 线程局部变量ThreadLocal 实现线程内的数据共享 存在ThreadLocalMap里 多线程行为一致操作同一数据源 使用同一个Runnable对象(携带共享数据) 多线程行为不一致操作同一数据源 1.共享数据封装到一个对象被不同Runnable获取 2Runnable对象作为内部类 贡献数据作为外部类的成员变量
wait()和sleep()区别 wait会释放锁 sleep会占有锁 wait用于进程间交互 sleep用于暂停执行 notify()唤醒一个等待线程 notifyAll() 唤醒所有
Volatile关键字:保证了不同线程对这个数据操作的可见性 并且禁止指令重排序 本质是告诉jvm当前值在寄存器中是不确定的 要去主存读取 仅变量级别 不保证原子性 不会造成线程堵塞 不会被编译器优化 synchronized关键字:锁定当前变量,只有当前线程可以访问,其他线程被阻塞 变量方法类均可使用 保证原子性 会造成线程堵塞 可以被编译器优化
同一个类中的两个方法都加了同步锁 可以同时访问吗?Lock可以让等待锁的线程中断,获取锁再释放锁 所以不可以同时访问 synchronized访问的是同一把锁,可以访问它的其他synchronized方法
死锁:多个线程因资源竞争形成僵局无法推进 必要条件:互斥 不剥夺 请求保持 循环等待 死锁避免:加锁顺序 加锁时限
多线程通信机制: 共享变量 wait/notify机制(例生产者消费者机制)
线程进程区别:进程资源分配和调度的独立单位 线程是进程的实体
启动线程:start()方法 run()是线程启动进行的回调方法callback
并发库 Concurrent库 atomic包 原子操作 volatile修饰的变量 线程每次访问都会读取修改后最新的值 并且没有原子性 Lock() 锁 Lock()接口支持语义不同的锁规则 ReadWriteLock()接口 读写锁 Condition()接口 描述与锁有关的条件变量
线程池:限制线程数量 减少资源浪费 减少重复创建销毁 重复利用 若不使用线程池 一个线程结束就无法再次使用 会报错 ExecutorsService:线程池接口 Executors 执行接口:newFixedThreadPool(n) 固定大小线程池 newCachedThreadPool() 缓存大小线程池 newSingleThreadool()单线程池 newScheduledThreadPool() 无限线程池
任务执行:execute(Runnable) 异步执行 无法得知执行结果 submit(Runnable) 返回一个Future对象 得知执行结果 submit(Callable)可以通过Future对象获得call函数结果 invokeAny()执行一系列call函数 返回其中一个callable结果 invokeAll()执行一些列call函数返回所以结果
结束:shutdown()只shut空闲线程 shutdownNow() 全部都中断 包括执行的
线程数量corePoolSize指定线程池的核心线程数,即线程池中始终保持的最小线程数。即使这些线程处于空闲状态,它们也不会被销毁。核心线程负责处理任务队列中的任务,保证基本的任务处理能力。 maxPoolSize指定线程池的最大线程数,即线程池中允许存在的最大线程数。当任务队列中的任务数超过核心线程数,并且线程池中的线程数小于最大线程数时,线程池会创建新的线程来处理任务。当任务数减少时,线程池会逐渐销毁多余的线程,以节省资源。
SheduledPoolExecutor 可以异步执行 或多次执行 不一定给当时分配的线程执行
ForkJoinPool 可以将任务进行分割给不同cpu的线程执行 子任务执行结束后将结果进行合并
RecursiveAction 没有返回值的任务 RecursiveTask 会返回结果的任务 需要合并
并发队列
阻塞队列
BlockingQueue(满了加入阻塞 空了退出阻塞) 四种处理方式 抛异常 返回特殊值 一直阻塞 超时退出 公平锁:先查再用 非公平锁:直接尝试占用
ArrayBlockingQueue数组实现
offer() 队尾插入 成功true 队满返回false put()队尾插入 满了等待有空位插入返回 poll()队头移除 空队列返回null take()队头移除 空则等待有元素再返回 peek()返回队首不移除 空返回null size() 加了独占锁 计算时不能移动元素
DelayQueue 对元素持有到一个特定延迟到期 延迟期满才能取出元素 优先级比较的基准是时间
LinkedBlockingQueue 两个结点放置首尾结点 count记录原子个数
PriorityBlockingQueue 无界并发队列 按你实现的comparable决定执行哪个 堆结构 独占锁 同时只有一个可以进行操作
tryGrow 扩容时释放锁 允许其它线程操作,但是其它也可能进行扩容 所以将扩容操作加入一个锁 copy时要加锁 防止数据不一致
SynchronousQueue 只容纳一个元素 同步队列 通信匹配机制
公平机制:先进入的先被匹配
非公平机制:后进入的先被匹配 栈
Tomcat中的TaskQueue继承了LinkedBlockingQueue 泛型类型固定成了Runnable
执行时,如果当前线程数小于corePoolSize创建新线程执行该任务 大于等于CorePoolSize 任务放在阻塞队列 若队列满了 当前线程数小于maxPoolSize 创建新线程运行该任务 大于等于maxPoolSize 线程池抛出异常 任务执行完毕并且线程大于corepoolsize 则回收一些线程保持corepoolsize
非阻塞队列 CAS Compare and swap 需要读写位置V 进行比较的值A 要写入的新值B 只有V的值等于A,才会通过原子方式用B更新V的值
悲观锁:通过独占锁避免悲剧发生
乐观锁:认为冲突是可发现和避免的 等出现冲突再处理
ConcurrentLinkedQueue 非阻塞无界链表队列
ConcurrentSkipListMap 线程安全 跳表实现
Atomic 类 自动实现多线程 不用关键字 CAS方法
Java内部类
静态嵌套类 被声明为静态的内部类 可以不依赖外部类实例就被实例化 内部类:需要在外部类实例化后才能实例化
sql
语法
INNER JOIN 内连接返回两个表匹配的所有行,不匹配的不返回 OUNER JOIN外连接 分为LEFT JOIN和RIGHT JOIN 分别返回满足所有条件的所有行以及保留不满足条件的左表/右表,不满足条件的另一半表用null补足
OFFSET 指定数据的偏移量 比如查第二大的数字 OFFSET 1 LIMIT 指定返回数据的条数 也可以两个参数表示从哪开始 跳过 读取多少条 limit()方法中不能参与运算
IFNULL是一个在SQL中常用的函数,用于处理空值(NULL)情况。它接受两个参数:要检查的表达式和替代值。如果表达式的值为NULL,IFNULL函数将返回替代值;如果表达式的值不为NULL,则返回表达式的值
DISTINCT用于从查询结果中消除重复的行,只返回唯一的行
RANK() 会跳过相同数量的值 1,1,3 DENSE_RANK() 为每个数据分配唯一的位次,相同的值会得到相同的位次。位次将按照排名顺序递增,不会跳过相同值的数量 1,1,2,3 DENSE_RANK() OVER(ORDER BY score desc) as 'Rank'
窗口函数 lead(列名,offset, 默认值):向后偏移 offset 的列值; lag(列名,offset, 默认值) :向前偏移 offset 的列值;
JAVASE高级
反射
首先要获得要反射的类的字节码 Class.forName(className) 类名.class this.getClass() 然后将字节码中的方法 变量构造函数等映射成相应的Methods Filed Constructor 等使用
动态代理和静态代理 静态代理通常只代理一个类 动态代理代理一个接口下的多个类 静态代理事先知道自己要代理什么 动态代理只有运行才知道 动态代理的实现是JDK里的InvocationHandler接口的invoke方法,代理的是接口 业务类必须实现接口 通过Proxy里的newProxyInstance得到代理对象 另一种动态代理是CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现接口,动态的修改字节码达到修改类的目的
设计模式
创造型模式
工厂方法模式
普通工厂模式:建立一个工厂类 对实现同一接口的类进行实例创建
多个工厂方法模式:提供多个工厂方法,分别创建对象 改进
静态工厂方法模式:将工厂方法设置为静态 不需要创造实例 可以直接调用
抽象工厂模式:创建多个工厂类 需要增加功能时创建新的工厂类 维持闭包原则
单例模式
懒汉式(有需要再创建) 饿汉式(直接创建对象)
建造者模式
将各种产品集合起来管理 创建复合对象(某个类具有不同的属性)
原型模式
结构型模式
适配器模式
将某个类的接口转换成客户期待的另一个接口表示 消除由于接口的不匹配造成类的兼容性问题 主要分为三种 : 类的适配器 对象的适配器 接口的适配器
装饰器模式
给一个对象动态的增加一些新的功能 要求装饰对象和被装饰对象实现同一个接口 装饰对象持有被装饰对象的实例
代理模式
外观模式
桥接模式
组合模式
享元模式
行为型模式
策略模式
定义了一系列算法 并将算法进行封装,使他们可以相互替换,且不影响客户使用 需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,外部用户决定使用哪个算法
模板方法模式
观察者模式
订阅 当一个对象发生变化时,依赖该对象的对象都会收到通知,并且随之变化
迭代子模式
责任链模式
命令模式
状态模式
备忘录模式
访问者模式
中介者模式
解释器模式
JVM垃圾回收
搜索算法
引用计数器算法(废弃):给每个对象设置一个计数器 有引用+1 取消引用 -1 当为0时认为是垃圾可以回收 实现简单 效率高 但是无法解决循环引用问题 开销较大
跟搜索算法:GCroot对象(虚拟机栈中的引用对象 方法区域中的类静态属性引用对象 常量引用对象 本地方法栈Native 引用对象)为起点开始往下搜索,通过的路径称为引用链,对象没被引用链链接则认为是不可用的
回收算法
标记清除法(DVM使用),标记阶段标记要回收的对象,清除阶段紧随标记,将标记阶段确定不可用对象清除 效率不高 且可能剩余不连续内存空间
复制算法 把内存分成大小相同的块,每次使用其中的一块,垃圾回收时把存活对象复制到另一块,然后把这块清理,实现简单 运行效率高 只能用一半内存利用率低
标记整理法:标记类似 只是把存活对象往内存一端移动 提高内存利用率
分代收集:根据对象存活时间分为新生代和老年代,不同代采用不同算法 新生代复制算法 老年代标记整理法
内存泄漏
可能存在无用且可达的对象无法回收
内存溢出解决方法
修改JVM启动参数 增加内存 检查错误日志 对代码进行分析
JVM内存结构
内存模型
方法区:静态分配编译器将变量绑定在某个存储位置上而且这些绑定不会在运行时改变 常数池 代码中的命名变量 static变量 String 存储在这
JAVA栈
方法调用 记录方法帧
JAVA堆
以随意的顺序,在运行时进行存储空间分配和收回的内存管理模型 存储大小数量和声明周期无法确定的数据 如对象
内存分配
基础数据类型直接在栈分配 方法的形参在栈分配 函数调用完回收
引用数据类型 要用new来创建 既在栈分配空间 也在堆分配类变量
方法的引用参数,在栈空间分配一个地址空间,并指向堆空间的对象区,当方法调用完后从栈空间回收;
局部变量new出来时,在栈空间和堆空间中分配空间,当局部变量生命周期结束后,栈空间立刻被回收,堆等待GC回收
方法调用时传入的实际参数,先在栈空间分配,在方法调用完成后从栈空间释放;
字符串常量在DATA区域分配, this在堆空间分配;
数组既在栈空间分配数组名称,又在堆空间分配数组实际的大小!
引用类型
强引用:绝对不会被垃圾回收 内存不足报错也不回收
软引用:内存空间足够不会回收 内存不足将会回收 只要没被回收就一直可以使用 适用于内存敏感的高速缓存
弱引用
可有可无的对象 被扫描到随时清除
虚引用
不决定对象生命周期 与没引用一样 主要跟踪对象被垃圾回收的活动 必须和引用队列联合使用
类加载器
根类加载器Bootstrap
扩展类加载器Extension
系统应用类加载器
自定义类加载器(继承ClassLoader)
类型安全四沙箱: 类加载体系(双亲委派机制) .class文件检验器 内置JAVA虚拟机的安全特性 安全管理器及API
双亲委托机制 AppClassLoader->ExtensionClassLoader->BootstrapClassLoader->ExtensionClassLoader->AppClassLoader
类初始化时间
创建类的实例(new 一个对象) 访问类或接口的静态变量 调用类的静态方法 反射 初始化类的子类 JVM启动时标明的启动类
Lambda表达式
(params)->expression/statement {statements}
Predicate
IntSummaryStatistics
与匿名内部类的区别
内部类this表示这个类 lambda 表示使用表达式的类
编译方式不同 内部类会生成class文件 lambda会编译成类的私有方法 派发invokedynamic字节码指令调用
Optional类
可以为null的容器对象
javaWeb基础
原生JDBC操作数据库流程
1.Class.forName()加载数据库连接驱动 2.DriverManager.getConnection()获取数据连接对象 3.根据SQL获取sql会话对象 Sataement PreparedStatement .4执行SQL处理结果集,设置参数 5.关闭结果集 关闭会话 关闭连接
PreparedStatement 包含已经编译的SQL语句 执行速度更快 execute executeQuery executeUpdate 不再需要参数 不宜使用statement的原因:1代码的可读性和维护性不好 需要不断拼接 2.preparedStatement 尽最大可能提高性能 DB有缓存机制 3.提高了安全性,Statement容易被SQL注入 而PreparedStatement不会发生匹配
连接池
为数据库建立一个缓冲池 1.从连接池获取或创建连接 2.使用完毕后将连接返回给连接池 3.系统关闭前断开所有连接并释放连接占用的资源 4.处理无效连接 限制连接总数在范围之内
HTTP
长连接和短连接:HTP1.1默认长连接 数据传输完成保持TCP连接不断开,等待同域名下继续使用这个通道传输数据 反之短连接 HTTP1.0默认使用短连接 浏览器和服务器进行一次HTTP操作就建立一次连接,任务结束就中断连接
HTTP1.0 1.1区别
可扩展性:HTTP1.1在消息中增加版本号用于兼容性判断, 增加了OPTIONS方法 允许客户端获得一个服务器支持的方法列表 为了与未来协议兼容 在请求头内包含了Upgrade头域 通过该头域 客户端可以让服务器知道它支持的其它备用通信协议从而进行协议切换通信
缓存:1.0使用Expire头域判断资源的fresh或stale 并使用条件请求来判断资源是否有效 1.1在1.0基础上增加了cache的新特性 当缓存对象的Age超过Expire时变成stale对象 不需要直接抛弃 而是与源服务器进行重新激活
带宽优化:1.0存在浪费带宽的现象 1.1在请求消息中引入了range头域,允许只请求资源的某个部分,在响应消息中Content-Range头域声明了返回的对象的长度和偏移量