# 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)
* 对象 * 对象的创建 * 对象的内存布局 * 对象头 * 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 没有完成