study/java/README.md

263 lines
17 KiB
Markdown
Raw Permalink Normal View History

2020-02-23 14:23:40 +00:00
# java 部分
## java基础知识
* 面向对象的三大特征
* 继承:继承是类与类的一种关系,比较像集合中的从属于关系。
* 封装:隐藏类的基本信息,不允许外部程序直接访问,而是通过该类的方法实现对隐藏信息的操作和访问。
* 多态:方法的重写、重载与动态连接构成多态性;
2020-03-14 09:10:02 +00:00
* 面向对象的六大原则 【参考[设计模式](https://git.zeekling.cn/java/designPattern/src/branch/master/principle)】
2020-02-23 14:23:40 +00:00
* 单一职责原理:一个类只负责一项职责。
* 里氏替换原则:劲量不要重写父类的已经实现了的方法,可以用接口等其他方法绕开。
* 依赖倒置原则:高层模块不应该依赖底层模块,二者应依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
* 接口隔离原则:客户端不应该依赖其他不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
* 迪米特法则:又叫做最小知道原则。就是一个类对自己依赖的类知道越少越好。
* 开闭原则:尽量通过扩展软件实体行为来实现变化。
* 数据类型
* 基本数据类型
* 数值类型
* 整型:int(4字节)、short(2字节)、long(8字节)、char(2字节)、byte(1字节)、
* 浮点型:float(4字节)、double(8字节)
* boolean: boolean(1字节)
* 引用数据类型:数组、对象
* 强引用:用关键`new`出来的对象,强引用锁指向的对象在任何时候都不会被回收
* 软引用:用来描述有用但非必须的对象,在内存不足的时候可以回收
* 弱引用:用来描述非必须的对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发送之前。
* 虚引用:虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个持有虚引用的对象,和没有引用几乎是一样的,随时都有可能被垃圾回收器回收。
* java集合
2020-03-14 09:10:02 +00:00
![集合类总图](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/list.png)
2020-02-23 14:23:40 +00:00
* Collection:集合类的根接口list和set都继承自此接口
* List有序,可以重复一般用index标示顺序
* LinkedList底层用双链表实现:增加删除效率高
* ArrayList底层用数组实现:查找效率高
* Vector实现了一个动态数组。和ArrayList相似但是有以下不同vector是同步的
vector包含了许多传统方法或者只是需要一个可以改变大小的数组的情况。
* Stack:先进后出
* set无序不能有重复的元素
* HashSet:HashSet不存入重复元素的规则.使用hashcode和equals
* LinkedHashSet:是对LinkedHashMap的简单包装对LinkedHashSet的函数调用都会转换成合适的LinkedHashMap方法
* TreeSet:让存入的元素自定义比较规则;给TreeSet指定排序规则
* Queue
* Map由键值对组成,和Collection完全不相干是另一个接口
* Hashtable同步的、线程安全的不能接受为null的键值不到万不得已不要使用。
* HashMap非同步、线程不安全,一般不要求线程安全的情况下建议使用
* LinkedHashMap: 是HashMap+LinkedList即它既使用HashMap操作数据结构又使用LinkedList维护插入元素的先后顺序。
java 7 hashmap实现原理
2020-03-14 09:10:02 +00:00
![hashmap实现原理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/hashmap1.jpeg)
2020-02-23 14:23:40 +00:00
java8 实现原理
2020-03-14 09:10:02 +00:00
![java8 实现原理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/hashmap2.png)
2020-02-23 14:23:40 +00:00
* ConcurrentHsahMap可以用来代替HashTable而且比HashTable的扩展性好。
2020-03-14 09:10:02 +00:00
![ConcurrentHsahMap实现原理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/ConcurrentHashMap.png)
2020-02-23 14:23:40 +00:00
* TreeMap:是一个有序的key-value集合它是通过红黑树实现的。是SortedMap的一个实现类
* WeakHashMap:
* IdentifyHashMap:
* 并发集合类
* java.util.concurrent
* Executor:一个接口其定义了一个接收Runnable对象的方法executor其方法签名为executor(Runnable command),
* ExecutorService:是一个比Executor使用更广泛的子类接口其提供了生命周期管理的方法以及可跟踪一个或多个异步任务执行状况返回Future的方法
* Futurecallable实现的存在返回值的并发编程
* CountDownLatch可以用来在一个线程中等待多个线程完成任务的类
* Vector
* io流
2020-03-14 09:10:02 +00:00
![io详解](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/io.png)
2020-02-23 14:23:40 +00:00
* 根据处理数据的类型
* 字节流:字节流因为操作的是字节,所以可以用来操作媒体文件。
* 字符流字符流中的对象融合了编码表也就是系统默认的编码表。我们的系统一般都是GBK编码。字符流只用来处理文本数据字节流用来处理媒体数据。
* 根据数据流向
* 输入流
* 输出流
* RandomAccessFile:
* 对象序列化
* NIO(非阻塞IO)
* IO和NIO的区别
2020-03-14 09:10:02 +00:00
![IO和NIO的区别](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/nio_and_io.png)
2020-02-23 14:23:40 +00:00
* AIO (异步IO)
* 多线程
* 多线程的实现方式
* 继承自Thread类(不能线程共享)
* 实现Runnable接口(不可以返回值)
* 实现Callable接口(可以抛出异常、返回值)
* ThreadPoolExecutor
* ThreadPoolExecutor的策略
* 线程数量未达到corePoolSize则新建一个线程(核心线程)执行任务
* 线程数量达到了corePools则将任务移入队列等待
* 队列已满,新建线程(非核心线程)执行任务
* 队列已满总线程数又达到了maximumPoolSize,就会(RejectedExecutionHandler)抛出异常
* 常见四种线程池
* CachedThreadPool:线程数无限制;有空闲线程则复用空闲线程,若无空闲线程则新建线程;一定程序减少频繁创建/销毁线程,减少系统开销.
* FixedThreadPool:可控制线程最大并发数(同时执行的线程数);超出的线程会在队列中等待
* ScheduledThreadPool:支持定时及周期性任务执行。
* SingleThreadExecutor:有且仅有一个工作线程执行任务;所有任务按照指定顺序执行,即遵循队列的入队出队规则
* Executors
* 线程同步
* 同步方法:
* 同步代码块:synchronized 关键字在编译之后会在同步块的前后加上monitorenter和monitorexit,在执行monitorenter时需要获取锁如果占用所得对象是自己则需要将锁计数器加1,monitorexit时将锁计数器减1如果为0则释放锁
* 关键字volatile:
* 防止指令重排
* 编译器重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序;
* 处理器重排序。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序;
* 实现可见性,不保证原子性
* 可见性volatile保证线程所在空间中的volatile修饰的变量的值是最新的;
* 不保证原子性:两个线程对volatile修饰的变量同时进行赋值操作可能导致两个线程对该变量进行一次赋值。
* Reentrantlock:可重入锁,synchronized和Reentrantlock都是重入锁区别如下:
* synchronized:
1. 依赖JVM实现加入偏向锁之后性能和Reentrantlock差不多了
2. 使用比较方便简洁,由编译器去实现加锁和释放;
3. 只能是非公平锁;
* Reentrantlock:
1. 主要依赖代码控制实现,可以避免进入内核态的阻塞;
2. 需要手动加锁和释放锁,容易由于忘记释放锁导致死锁;
3. 既可以是公平锁也可以是非公平锁;
4. 提供Condition类可以分组唤醒线程
5. 能够中断等待线程;
* 使用局部变量实现线程的同步,如:ThreadLocal。
* 相关名词
* 对象锁、互斥锁、共享锁、公平锁、非公平锁([公平锁和非公平锁的比较](http://blog.csdn.net/fw0124/article/details/6672522))、
* 偏向锁:它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向
锁的线程将永远不需要触发同步。如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,
JVM会尝试消除它身上的偏向锁将锁恢复到标准的轻量级锁。引入偏向锁是为了在无多线程竞争的情况下尽量
减少不必要的轻量级锁执行路径。
* 原子操作、原子性、可见性
* [悲观锁和乐观锁 ](http://www.hollischuang.com/archives/934)
* [共享锁和排他锁](http://www.hollischuang.com/archives/923)
* 线程的交互
* notify()、 notifyAll()、wait()
* 反射
## java虚拟机
### 简述
java虚拟机我看过周志明的《深入理解java虚拟机》和周志明等人翻译的《java虚拟机规范(java SE 8版)》
### 结构
* 内存管理
* 虚拟机栈(非共享):
* 栈帧
* 局部变量表:局部变量数组包含了方法执行过程中的所有变量,包括 this 引用、所有方法参数、其他局部变量。
* 返回值:
* 操作数栈
* 类当前方法的运行时常量池引用
* java堆共享堆包括新生代( Eden、Survivor(from)、Survivor(to) )、老年代。
* 本地方法栈(非共享)
* 程序计数器(非共享)
* 方法区共享也可以说在堆中方法区又叫非堆用来区分对内存在hotsport虚拟机中方法区又叫做永久带.用来存放类信息,常量等和类相关的数据.
* 元空间:1.8引入的,用来替换方法区(永久代);不再虚拟机中,使用的是本地内存,取决于电脑的内存大小
***内存结构图***
1.7及以前版本java内存分布图
2020-03-14 09:10:02 +00:00
![jvm内存管理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/jvm.jpg)
2020-02-23 14:23:40 +00:00
1.8 内存分布图:
2020-03-14 09:10:02 +00:00
![jvm内存管理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/jvm.png)<br>
2020-02-23 14:23:40 +00:00
* 对象
* 对象的创建
* 对象的内存布局
* 对象头
* MarkWord:对象的MarkWord部分占4个字节其内容是一系列的标记位比如轻量级锁的标记位偏向锁标记位等等。
* Class对象指针:其指向的位置是对象对应的Class对象其对应的元数据对象的内存地址.
* 实例数据:存放属性信息,包括父类的信息。
* 对齐填充(有些对象没有,具体不太懂):Java对象在内存中将以8字节对齐也就是对象的总大小必须是8字节的整数倍。
* 对象的访问
* 指针方式访问hotspot 虚拟机用的就是指针方式访问):指针访问方式访问方式比句柄方式快,节省一次指正定位带来的时间开销。
* 句柄方式访问其他虚拟机句柄池中存放的是稳定的句柄当对象被移动时只需要改变句柄的实例数据就行不需要改变reference本身的值。
***普通对象的内存分布***
2020-03-14 09:10:02 +00:00
![mei对象](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/object.JPEG)
2020-02-23 14:23:40 +00:00
***数组对象的内存分布***
2020-03-14 09:10:02 +00:00
![mei对象](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/object_arr.JPEG)
2020-02-23 14:23:40 +00:00
* 垃圾回收
* 判断对象已死
* 引用计数法(无法判断循环引用的对象是否已死):每个对象都有一个引用计数器对象每被引用一次就加1对象被释放就减1引用计数为0表示可以被回收。
* 可达分析法如果对象能够到达root就认为对象不可回收。root对象
* 被启动类bootstrap加载器加载的类和创建的对象
* jvm运行时方法区类静态变量(static)引用的对象
* jvm运行时方法去常量池引用的对象
* jvm当前运行线程中的虚拟机栈变量表引用的对象
* 本地方法栈中(jni)引用的对象
* 垃圾收集算法
* 标记-清除算法(老年代,标记-清理算法容易产生碎片):标记阶段标记可回收的对象,请理阶段清理被标记的对象所占用的空间
* 复制算法(新生代,由于新生代对象存活较少,利用复制算法效率较高):按内存将容量将内存分为等大小的两块,每次只使用其中的一块,当一块的内存满了之后将存活对象复制到另一块上面去。
* 标记-整理算法(老年代):标记阶段标记可回收的对象,整理阶段将存活的对象移动到对象的另一边,清除边界以外的对象。
* 分代收集算法:新生代用复制算法(新生代存活的对象比较少),老年代用标记-清除和标记-整理算法
* 垃圾收集器(共六个垃圾收集器)
* 新生代收集器(新生代收集器一般都利用复制算法)
* Serial收集器复制算法
* ParNew收集器复制算法
* Parallel Scavenge收集器复制算法
* 老年代收集器
* Serial Old 收集器(标记-整理算法)
* CMS收集器标记-清除算法): 初始标记、 并发标记、 重新标记、 并发清除
* Parallel Old 收集器(标记-整理算法)
* G1收集器
* 步骤 初始标记、 并发标记、最终标记、筛选标记
* 特点: 并行与并发、分代收集、空间整合、可预测停顿
* class 文件
* class文件的结构
* 魔数:判断class文件是否被虚拟机接受的Class文件魔术固定值是0xCAFEBABE
* 版本号(主版本号、次版本号):主板本和副版本共同构成了Java文件的格式版本
* 访问标志(标识一些类或者接口的访问信息):用于表示某个类或者接口的访问权限及基础属性
* 类索引(this_class):this_class的值必须是对constant_pool表中项目的一个有效索引值,表示这个Class文件所定义的类或接口。
* 父类索引(super_class):对于类来说super_class的值必须为0或者是对constant_pool表中项目的一个有效索引值。
* 接口数/接口表:
* 字段计数器:它用于表示该类或接口声明的类字段或者实例字段。
* 常量池计数器:constant_pool_count的值等于constant_pool表中的成员数加1。
* 常量池(主要存放两大类常量),常量池的索引范围是1至constant_pool_count1。
* 字面量
* 符号引用
* 字段表集合(含有字段访问标志)
* 方法数/方法表:
* 属性数/属性表:
* 类加载机制
* 类加载过程
* 加载
* 链接
* 验证:
* 准备:为类变量等赋初始值。如:`public static int a = 123;` 初始值为0不是123.
* 解析:将符号引用转化为直接引用的过程。
* 初始化
* 使用
* 卸载
* 双亲委派模型
* 启动类加载器:加载`${JAVA_HOME}/jre/lib/`下面的jar包所有以`java.*`的class都是由启动类加载器加载的。
* 扩展类加载器:加载`${JAVA_HOME}/jre/ext/*.jar`
* 应用程序类加载器:用户指定的类。
* 用户自定义类加载器:
* 破坏双亲委派模型
* 线程上下文类加载器
* 虚拟机字节码执行引擎(这部分还没有看懂,就不具体列提纲了)
*
* 高效并发
* 内存间的交互
* lock锁定作用于主存的变量
* unlock解锁作用于主存的变量
* read读取作用于主存的变量
* load载入作用于工作内存的变量
* use使用作用于工作内存的变量
* assign赋值作用于工作内存的变量
* store存储作用于工作内存的变量
* write写入作用于主存的变量
## 算法部分
### 简述
java部分我主要看过[《剑指offer》](http://pan.baidu.com/s/1c1ZmCww)和[《程序员面试金典》](http://www.duokan.com/book/63706)两本书。感觉两本书都挺不错的。
### 《 剑指offer》
[剑指offer面试题目](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker/offer)
### 《 程序员面试金典》
#### 面试考题型目录
* [数组与字符串](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker/test/test1)
* [链表](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker/test/test2)
* [栈与队列](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker)
* [树与图](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker)
* [位操作](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker)
* [智力题](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker)
* [数学与概率](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker)
* [面向对象设计](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker)
* [递归和动态规划](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker)
* [扩展性与存储限制](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker)
* [排序与查找](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker)
### 脚本
脚本compile.sh 没有完成