263 lines
17 KiB
Markdown
263 lines
17 KiB
Markdown
# java 部分
|
||
|
||
## java基础知识
|
||
|
||
* 面向对象的三大特征
|
||
* 继承:继承是类与类的一种关系,比较像集合中的从属于关系。
|
||
* 封装:隐藏类的基本信息,不允许外部程序直接访问,而是通过该类的方法实现对隐藏信息的操作和访问。
|
||
* 多态:方法的重写、重载与动态连接构成多态性;
|
||
* 面向对象的六大原则 【参考[设计模式](https://git.zeekling.cn/java/designPattern/src/branch/master/principle)】
|
||
* 单一职责原理:一个类只负责一项职责。
|
||
* 里氏替换原则:劲量不要重写父类的已经实现了的方法,可以用接口等其他方法绕开。
|
||
* 依赖倒置原则:高层模块不应该依赖底层模块,二者应依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
|
||
* 接口隔离原则:客户端不应该依赖其他不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
|
||
* 迪米特法则:又叫做最小知道原则。就是一个类对自己依赖的类知道越少越好。
|
||
* 开闭原则:尽量通过扩展软件实体行为来实现变化。
|
||
* 数据类型
|
||
* 基本数据类型
|
||
* 数值类型
|
||
* 整型:int(4字节)、short(2字节)、long(8字节)、char(2字节)、byte(1字节)、
|
||
* 浮点型:float(4字节)、double(8字节)
|
||
* boolean: boolean(1字节)
|
||
* 引用数据类型:数组、对象
|
||
* 强引用:用关键`new`出来的对象,强引用锁指向的对象在任何时候都不会被回收
|
||
* 软引用:用来描述有用但非必须的对象,在内存不足的时候可以回收
|
||
* 弱引用:用来描述非必须的对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发送之前。
|
||
* 虚引用:虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个持有虚引用的对象,和没有引用几乎是一样的,随时都有可能被垃圾回收器回收。
|
||
* java集合
|
||
![集合类总图](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/list.png)
|
||
* 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实现原理
|
||
![hashmap实现原理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/hashmap1.jpeg)
|
||
java8 实现原理
|
||
![java8 实现原理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/hashmap2.png)
|
||
* ConcurrentHsahMap:可以用来代替HashTable,而且比HashTable的扩展性好。
|
||
![ConcurrentHsahMap实现原理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/ConcurrentHashMap.png)
|
||
* TreeMap:是一个有序的key-value集合,它是通过红黑树实现的。是SortedMap的一个实现类
|
||
* WeakHashMap:
|
||
* IdentifyHashMap:
|
||
* 并发集合类
|
||
* java.util.concurrent
|
||
* Executor:一个接口,其定义了一个接收Runnable对象的方法executor,其方法签名为executor(Runnable command),
|
||
* ExecutorService:是一个比Executor使用更广泛的子类接口,其提供了生命周期管理的方法,以及可跟踪一个或多个异步任务执行状况返回Future的方法
|
||
* Future:callable实现的存在返回值的并发编程
|
||
* CountDownLatch:可以用来在一个线程中等待多个线程完成任务的类
|
||
* Vector
|
||
* io流
|
||
![io详解](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/io.png)
|
||
* 根据处理数据的类型
|
||
* 字节流:字节流因为操作的是字节,所以可以用来操作媒体文件。
|
||
* 字符流:字符流中的对象融合了编码表,也就是系统默认的编码表。我们的系统一般都是GBK编码。字符流只用来处理文本数据,字节流用来处理媒体数据。
|
||
* 根据数据流向
|
||
* 输入流
|
||
* 输出流
|
||
* RandomAccessFile:
|
||
* 对象序列化
|
||
* NIO(非阻塞IO)
|
||
* IO和NIO的区别
|
||
![IO和NIO的区别](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/nio_and_io.png)
|
||
* 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内存分布图:
|
||
![jvm内存管理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/jvm.jpg)
|
||
1.8 内存分布图:
|
||
![jvm内存管理](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/jvm.png)<br>
|
||
* 对象
|
||
* 对象的创建
|
||
* 对象的内存布局
|
||
* 对象头
|
||
* MarkWord:对象的MarkWord部分占4个字节,其内容是一系列的标记位,比如轻量级锁的标记位,偏向锁标记位等等。
|
||
* Class对象指针:其指向的位置是对象对应的Class对象(其对应的元数据对象)的内存地址.
|
||
* 实例数据:存放属性信息,包括父类的信息。
|
||
* 对齐填充(有些对象没有,具体不太懂):Java对象在内存中将以8字节对齐,也就是对象的总大小必须是8字节的整数倍。
|
||
* 对象的访问
|
||
* 指针方式访问(hotspot 虚拟机用的就是指针方式访问):指针访问方式访问方式比句柄方式快,节省一次指正定位带来的时间开销。
|
||
* 句柄方式访问(其他虚拟机):句柄池中存放的是稳定的句柄,当对象被移动时,只需要改变句柄的实例数据就行,不需要改变reference本身的值。
|
||
***普通对象的内存分布***
|
||
![mei对象](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/object.JPEG)
|
||
***数组对象的内存分布***
|
||
![mei对象](https://git.zeekling.cn/zeekling/study/raw/branch/master/java/pics/object_arr.JPEG)
|
||
* 垃圾回收
|
||
* 判断对象已死
|
||
* 引用计数法(无法判断循环引用的对象是否已死):每个对象都有一个引用计数器,对象每被引用一次就加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_count−1。
|
||
* 字面量
|
||
* 符号引用
|
||
* 字段表集合(含有字段访问标志)
|
||
* 方法数/方法表:
|
||
* 属性数/属性表:
|
||
* 类加载机制
|
||
* 类加载过程
|
||
* 加载
|
||
* 链接
|
||
* 验证:
|
||
* 准备:为类变量等赋初始值。如:`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 没有完成
|