学习总结(2022.04.19-2022.04.24)
类加载器
分类:
- Bootstrap ClassLoader 根类加载器,负责核心类的加载
- Extension ClassLoader 扩展类加载器,负责扩展目录中jar包的加载
- Sysetm(App) ClassLoader 系统类加载器/应用加载器,负责自定义类的加载
- User ClassLoader 自定义类加载器,自定义的类加载器
双亲委派模型:当自定义类进行类加载时,并不是一开始就由系统类加载器进行加载的,而是会交给扩展类加载器,扩展类加载器又会交给根类加载器,但是根类加载器在核心类的jar包中找不到自定义的类,于是又会原路返回至系统类加载器,最后还是由系统类加载器执行。
注解
注解是代码里面的一些特殊标记,可以在编译、类加载、运行时被读取,并执行相应的处理。注解可以在不改变原有逻辑的情况下,补充一些信息。注解作为一种数据类型,跟class、interface具有同等地位。
注解的使用方式与修饰符一样,可以给任何一种数据写上注解(类、接口、构造器、变量…)
自定义注解:
1 | |
注解的使用:
1 | |
元注解:描述注解的注解。常用的元注解有:
@Retention元注解,来定义我们自己定义的注解的保留级别.1
2
3RetentionPolicy.RUNTIME
RetentionPolicy.CLASS // 默认
RetentionPolicy.SOURCE@Target元注解,注解可以作用的目标1
2
3
4ElementType.TYPE// 整个类
ElementType.FIELD// 成员变量
ElementType.CONSTRUCTOR// 构造方法
ElementType.METHO// 成员方法
GC
如何确定垃圾:
- 引用计数算法:给对象添加一个引用计数器,每当有引用指向它,计数器+1;每当引用失效,计数器-1。当计数器为0,表示该对象不可被引用。但是引用计数算法无法应用在循环引用中。
- 根搜索算法:以一个叫”GC Roots”的对象为起点向下搜索,看一个对象是否存在连接至GC Root的引用链,如果没有表示该对象不可被引用。GC使用根搜索算法。
如何回收垃圾:
标记清除算法:首先标记出所有需要回收的对象,再统一回收;或者标记出所有存活的对象,统一回收未被标记的对象。虽然实现简单,但是会产生很多内存碎片。
标记复制算法:将一块内存划分成容量相等的两块,每次使用其中一块,当内存用完后,将还存活的对象复制至另一块内存中,再把已满的内存全部清理。虽然实现简单且不容易产生内存碎片,但是内存利用率降低了,且存活对象较多时,会产生许多不必要的开销,降低效率。
标记整理算法:同标记清除算法一样,将所有需要回收的对象标记,但是它不会直接清理,而是将存活的对象都往一端移动,移动完成后清除边界外的所有对象。这样虽然不会产生内存碎片,但是效率却降低了。
分代收集算法:根据对象的存活时间将内存划分为新生代、老年代和永久代,新生代中的对象大部分都是存活时间较短的,老年代中的对象则是存活时间较长的。
新创建的对象会放入新生代中,新生代空间使用的是标记复制算法,将新生代空间划为一个eden空间和两个survivor空间(survivor1、survivor2),其中eden空间用来放置新建的对象,survivor1和survivor2则用来放置复制一遍和复制两遍后存活的对象。当过了一定时间后,survivor2中的对象会放至老年代。
老年代中因为存活对象较多,一般使用标记整理算法。
何时回收垃圾:
- 申请堆空间失败,表示堆空间已满,触发GC。
- 系统进入休眠一段时间触发GC。
- 主动调用GC。
设计模式
五大原则:
- 单一职责原则:每个类只负责自己的部分。
- 开闭原则:一个类或模块应该对拓展开放,对修改关闭。
- 里氏替换原则:任何父类可以出现的地方,子类都可以出现。
- 接口隔离原则:一个接口只提供一个对外的功能。
- 依赖倒置原则:上层模块不应该依赖于底层模块,而应该依赖于抽象类或接口;抽象类或接口不应该依赖于具体实现类,具体实现类应该依赖于抽象类或接口。
单例设计模式:
保证一个类只有一个对象,防止频繁的创建和销毁对象,避免对共享资源的多重占用。
实现方法:构造方法私有;提供返回实例的静态方法;提供自身类型的全局变量。
1 | |
工厂设计模式:
可以通过一个工厂批量生产对象,同时隐藏创建对象的一些细节,标准化产生实例。
1 | |