计算机基础
为什么浮点数会丢失精度?
因为在计算机中,浮点数只能表示(1/2)的幂,所以表示上可能存在不精确的情况
如何解决精度问题?
比如银行的话,会用分做货币单位,或者使用Java中的BigDecimal类
面向对象
Object类的六个方法
public final native Class> getClass();
public native int hashCode();
public boolean equals(Object obj);
public String toString();
public final native void notify();
public final native void notifyAll();
public final native void wait();
protected native Object clone();
protected void finalize();
访问控制权限
--------------------------------------------------
| 访问权限控制符 | 任何地方 | 包外子类 | 包内 | 类内 |
--------------------------------------------------
| public | OK | OK | OK | OK |
--------------------------------------------------
| protected | NO | OK | OK | OK |
--------------------------------------------------
| 无 | NO | NO | OK | OK |
--------------------------------------------------
| private | NO | NO | NO | OK |
--------------------------------------------------
序列化
1.Java 原生序列化 —— 通过实现Serializable接口来实现该类对象的序列化,这个接口非常特殊,没有任何方法,是个标记接口.
优点 —— 兼容性最好
缺点 —— 不支持跨语言且性能一般
2.Hessian 序列化
优点 —— 跨语言,且有压缩编码的功能,效率比Java原生序列化高
缺点 —— Hessian会把复杂对象所有属性存储在一个Map中进行序列化,所以在父类和子类有同名成员变量的情况下,Hessian序列化时,先序列化子类,然后序列化父类,因此反序列化结果会导致子类同名成员变量被父类的值覆盖.
3.JSON 序列化
优点 —— 可读性高
缺点 —— 容易被窃取,敏感属性最好加上transient关键字,进行加密单独传输
为什么要使用泛型
1.类型安全 —— 放置的是什么,取出来的就是什么,不用担心会抛出ClassCastException异常
2.提升可读性
3.代码重用 —— 泛型合并了相同类型的处理代码,使代码重用度变高
StringBuffer 和 StringBuilder
StringBuffer —— 线程安全,但是效率低
StringBuilder —— 非线程安全,但是效率高
JVM
为什么需要自定义类加载器
1.隔离加载类
2.修改类加载方式
3.扩展加载源
4.防止源码泄露
数据结构与集合
Map
Key —— Set
Value —— Collection
Arrays.sort() 和 Collections.sort()
其实Collections.sort()底层调用的是Arrays.sort(),所以我们只要分析Arrays.sort()就好了
如果数组长度大于等于286且连续性好的话,就用归并排序,如果大于等于286且连续性不好的话就用双轴快速排序.如果长度小于286且大于等于47的话就用双轴快速排序,如果长度小于47的话就用插入排序
https://blog.csdn.net/xlgen157387/article/details/79863301
泛型
List> —— 一般作为参数来接收外部的集合,或者返回一个不知道具体元素类型的集合
List extends T> —— Get First,适用于消费集合元素为主的场景 [可以赋值给任何T及T的子类]
List super T> —— Put First,适用于生产集合元素为主的场景 [可以赋值给任何T及T的父类]
Comparable 和 Comparator
Comparable —— public int compareTo(T o);
[适用于和别的对象比较,在一个对象构建的时候使用]
Comparator —— int compare(T o1, T o2);
[适用于比较同一种类型的对象,在对象构建完成后的补救]
红黑树
特性:
1.节点只能是红色或者黑色
2.根节点必须是黑色
3.所有NIL节点都是黑色的
4.一条路径上不能出现相邻的两个红色节点
5.在任何递归子树上,根节点到叶子节点的所有路径上包含相同数目的黑色节点
6.根节点到叶子节点的最长路径不超过最短路径的两倍
插入规则:
1.需要调整的新节点总是红色的
2.如果插入的节点的父节点是黑色的,则无需调整
3.如果插入新节点的父节点是红色的,需要进行旋转变色
并发与多线程
线程池的好处
1.利用线程池管理并复用线程、控制最大并发数等
2.实现任务线程队列缓存策略和拒绝机制
3.实现某些与时间相关的功能,如定时执行、周期执行等
4.隔离线程环境
线程池的核心参数
1.corePoolSize —— 常驻核心线程数
2.maximumPoolSize —— 最大线程数
3.keepAliveTime —— 线程空闲时间
4.TimeUnit —— 时间单位
5.workQueue —— 阻塞队列
6.threadFactory —— 线程工厂
7.handler —— 拒绝策略
五种常见的线程池:
1.newFixedThreadPool(int nThreads)
指定工作线程数量的线程池
2.newCacheThreadPool()
处理大量短时间工作任务的线程池
(1)试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程
(2)如果线程闲置的时间超过阈值,则会被终止并移出缓存
(3)系统长时间限制的时候,不会消耗什么资源
3.newSingleThreadExecutor()
创建唯一的工作者线程来执行任务,如果线程异常结束,会有另一个线程来取代它
4.newSingleThreadScheduledExecutor()和newScheduledThreadPool(int corePoolSize)
定时或者周期性的工作调度,两者的区别在于单一工作线程还是多个线程
5.newWorkStealingPool()
内部会构建ForkJoinPool,利用working-stealing算法,并行地处理任务,不保证处理顺序
线程池的几种拒绝策略:
AbortPolicy -- 直接抛出异常(默认策略)
CallerRunsPolicy -- 用调用者所在的线程来执行任务
DiscardOldestPolicy -- 丢弃队列中最靠前的任务,并执行当前任务
DiscardPolicy -- 直接丢弃任务
七种常见的BlockingQueue:
1.ArrayBlockingQueue -- 一个由数组结构组成的有界阻塞队列
2.LinkedBlockingQueue -- 一个由链表结构组成的有界/无界阻塞队列
3.PriorityBlockingQueue -- 一个支持优先级排序的无界阻塞队列
4.DealyQueue -- 一个使用优先级队列实现的无界阻塞队列
5.SynchronousQueue -- 一个不存储元素的阻塞队列
6.LinkedTransferQueue -- 一个由链表结构组成的无界阻塞队列
7.LinkedBlockingDeque -- 一个由链表结构组成的双向阻塞队列