目录
一、JDK JRE JVM 区别
1、英文全称
2、包含关系
二、Jdk1.7 - Jdk1.8
1、java虚拟机 变化
2、HashMap 变化(底层)
三、如何实现AOP
四、红黑树 Red-Black Tree
1、特性:
2、例图
3、应用
4、基本操作
五、 Java中的异常体系
六、String、StringBuffer、StringBuild
七、接口和抽象类的区别
八、CopyOnWriteArrayList的底层原理
一、JDK JRE JVM 区别
1、英文全称
JDK
Java Develpment kit java开发工具(提供给开发人员使用)
JRE
Java Runtime Environment java运行时环境(提供给用户运行java程序)
JVM
Java Virtual Machine java虚拟机(将class文件解释成机器码)
2、包含关系
JDK
Java Develpment kit java开发工具(提供给开发人员使用)
JRE
Java Runtime Environment java运行时环境(提供给用户运行java程序)
JVM
Java Virtual Machine java虚拟机(将class文件解释成机器码)
二、Jdk1.7 - Jdk1.8
1、java虚拟机 变化
1.7中存在永久代,1.8中没有永久代,替换它的是元空间,元空间所点的内存不在虚拟机内部,而是本地内存空间,这么做的原因是,不管是永久代还是元空间,他们都是方法区的具体实现,之所以元空间所占的内存改成本地内存,官方的说法是为了和JRockit统一,不过额外还有一些原因,比如方法区所存储的类信息通常是比较难确定的,所以对于方法区的大小是比较难指定的,太小了容易出现方法区溢出,太大了又会占用了太多虚拟机的内存空间,而转移到本地内存后则不会影响虚拟机所占用的内存。
2、HashMap 变化(底层)
- 1.7中底层是数组+链表,1.8中底层是数组+链表+红黑树①,加红黑树的目的是提高HashMap插入和查询整体效率
- 1.7中铠表插入使用的是头插法,1.8中链表插入使用的是尾插法,因为1.8中插入key和Value时需要判断链表元素个数,所以需要遍历链表统计链表元素个数,所以正好就直接使用尾插法。
- 1.7中哈希算法比较复杂,存在各种右移与异或运算,1.8中进行了简化,因为复杂的哈希算法的目的就是提高散列性,来提供HashMap的整体效率,而1.8中新增了红黑树,可以适当的简化哈希算法,节省CPU资源。
三、如何实现AOP
利用动态代理技术来实现AOP,比如JDK动态代理或Cglib动态代理,利用动态代理技术,可以针对某个类生成代理对象,当调用代理对象的某个方法时,可以任意控制该方法的执行,比如可以先打印执行时间,再执行该方法,并且该方法执行完成后,再次打印执行时间。
项目中,比如事务、权限控制、方法执行时长日志都是通过AOP技术来实现的,凡是需要对某些方法做统一处理的都可以用AOP来实现,利用AOP可以做到业务无侵入。
四、红黑树 Red-Black Tree
一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。
1、特性:
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
注意:
- 特性(3)中的叶子节点,是只为空(NIL或null)的节点。
- 特性(5),确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。
2、例图
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
注意:
- 特性(3)中的叶子节点,是只为空(NIL或null)的节点。
- 特性(5),确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。
3、应用
红黑树的应用比较广泛,主要是用它来存储有序的数据,它的时间复杂度是O(lgn),效率非常高。
例如,Java集合中的TreeSet和TreeMap,C++ STL中的set、map,以及Linux虚拟内存的管理,都是通过红黑树去实现的。
4、基本操作
红黑树的基本操作是添加、删除。在对红黑树进行添加或删除之后,都会用到旋转方法。因为添加或删除红黑树中的节点之后,红黑树就发生了变化,可能不满足红黑树的5条性质,也就不再是一颗红黑树了,而是一颗普通的树。而通过旋转,可以使这颗树重新成为红黑树。简单点说,旋转的目的是让树保持红黑树的特性。
旋转包括两种:左旋 和 右旋
五、 Java中的异常体系
Java中的所有异常都来自顶级父类Throwable。Throwable下有两个子类Exception和Error。
Error是程序无法处理的错误,一旦出现这个错误,则程序将被迫停止运行。
Exception不会导致程序停止,又分为两个部分RunTimeException运行时异常和CheckedException检查异常。
RunTimeException常常发生在程序运行过程中,会导致程序当前线程执行失败。CheckedException常常发生在程序编译过程中,会导致程序编译不通过。
六、String、StringBuffer、StringBuild
String是final修饰的,不可变,每次操作都会产生新的String对象 StringBuffer和StringBuilder都是在原对象上操作
StringBuffer是线程安全的,StringBuilder线程不安全的 StringBuffer方法都是synchronized修饰的
性能: StringBuilder > StringBuffer > String
场景:经常需要改变字符串内容时使用后面两个
优先使用StringBuilder,多线程使用共享变量时使用StringBuffer
七、接口和抽象类的区别
- 抽象类可以存在普通成员函数,而接口中只能存在public abstract方法。
- 抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型。
- 抽象类只能单继承,接口可以多实现。
接口的设计目的,是对类的行为进行约束("有"约束,因为接口不能规定类不可以有什么行为),可以强制要求不同的类具有相同的行为,但不对如何实现行为进行限制。
抽象类的设计目的,是代码复用。当不同的类具有某些相同的行为(记为行为集合A),且其中一部分行为的实现方式一致时(A的非真子集,记为B),可以让这些类都派生于一个抽象类。在这个抽象类中实现了B,避免让所有的子类来实现B,这就达到了代码复用的目的。而A减B的部分,留给各个子类自己实现。正是因为A-B在这里没有实现,所以抽象类不允许实例化出来(否则当调用到A-B时,无法执行)。
抽象类是对类本质的抽象,表达的是is a的关系,比如:五菱宏光 is a car。抽象类包含并实现子类的通用特性,将子类存在差异化的特性进行抽象,交由子类去实现。
而接口是对行为的抽象,表达的是like a的关系。比如: Bird like a Airplane。接口的核心是定义行为,即实现类可以做什么,至于实现类主体是谁、是如何实现的,接口并不关心。
使用场景:当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。
抽象类的功能要远超过接口,但是,定义抽象类的代价高。因为高级语言来说(从实际设计上来说也是)每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。
八、CopyOnWriteArrayList的底层原理
ArrayList线程不安全
- 首先CopyOnWriteAraylit内部也是用过数组来实现的,在向CopyOnWriteAravList添加元素时,会复制一个新的数组,写操作在新数组上进行,读操作在原数组上进行
- 并且,写操作会加锁,防止出现并发写入丢失数据的问题
- 写操作结束之后会把原数组指向新数组
- CopyOnWriteArrayList允许在写操作时来读取数据,大大提高了读的性能,因此适合读多写少的应用场景,但是CopyOnWriteArayList会比较占内存,同时可能读到的数据不是实时最新的数据,所以不适合实时性要求很高的场景



