静态代理:须要代理对象和目标对象实现同样的接口。
同一个接口,一个目标类实现,一个代理类实现,代理类除了目标类的方法还有别的加强方法
优势:能够在不修改目标对象的前提下扩展目标对象的功能。
缺点:1冗余。因为代理对象要实现与目标对象一致的接口,会产生过多的代理类。
2不易维护。一旦接口增长方法,目标对象与代理对象都要进行修改。java
JDK动态代理:使用JDK的API动态地在内存中构建代理对象,从而实现对目标对象的代理功能.
一个代理类能代理多个类型(实现多个类)
静态代理编译时就已实现,是实际的class文件,而动态代理编译完没有实际的class文件,而是在运行时动态生产类字节码,并加载到JVM中
动态代理对象不须要实现接口,可是要求目标对象必须实现接口,不然不能使用动态代理。
JDK动态代理必须实现InvocationHandler接口,加强内容写invoke就好了算法
cglib动态代理:使用第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展
代理没有接口的类的时候使用,使用cglib代理的对象则无需实现接口,达到代理类无侵入
应用的是底层的字节码加强的技术 生成当前类的子类对象设计模式
性能:
1静态代理在编译时产生class字节码文件,能够直接使用,效率高。
2动态代理必须实现InvocationHandler接口,经过反射代理方法,比较消耗系统性能,但能够减小代理类的数量,使用更灵活。
3cglib代理无需实现接口,经过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib会继承目标对象,须要重写方法,因此目标对象不能为final类。安全
动态代理和静态代理的比较
动态代理与静态代理相比较,最大的好处是接口中声明的全部方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,咱们能够进行灵活处理,而不须要像静态代理那样每个方法进行中转。并且动态代理的应用使咱们的类职责更加单一,复用性更强数据结构
设计模式:
1单例设计模式:懒汉式,饿汉式
懒单例模式时注意线程安全问题
饿单例模式和懒单例模式构造方法都是私有的,于是是不能被继承的
2工厂模式:
普通工厂:输入类型,得到类型的实例
多个工厂方法模式:提供多个工厂方法,建立对象调用不一样的方法
静态工厂方法:将上面工厂方法模式里面的方法置为静态,不用建立实例,直接调用便可
抽象工厂方法:以前几种依赖工厂类,若是修改要改源码,违反闭包的原则,解决方法:建立多个工厂类,这样一旦须要增长新的功能,直接增长新的工厂类就能够了,不须要修改以前的代码。
3建造者模式:
工厂类模式提供的是建立单个类的模式,而建造者模式则是将各类产品集中起来进行管理,用来建立复合对象,所谓复合对象就是指某个类具备不一样的属性
4适配器设计模式
适配器模式将某个类的接口转换成客户端指望的另外一个接口表示,目的是消除因为接口不匹配所形成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式
经过引入一个适配器类来重用现有的适配者类,无需修改原有结构
5装饰模式
装饰模式就是给一个对象增长一些新的功能,并且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例
(代理有对象控制权,装饰只能增强功能)
6策略模式
策略模式的决定权在用户,系统自己提供不一样算法的实现,新增或者删除算法,对各类算法作封装。所以,策略模式多用在算法决策系统中,外部用户只须要决定用哪一个算法便可
7观察者模式
当一个对象变化时,其它依赖该对象的对象都会收到通知,而且随着变化!对象之间是一种一对多的关系闭包
JVM垃圾回收机制:主要进行回收的内存是 JVM 中的方法区和堆
搜索算法:根搜索算法“GC Roots”对象做为起点,从这些节点开始往下搜索,搜索经过的路径成为引用链
(Reference Chain),当一个对象没有被 GC Roots 的引用链链接的时候,说明这个对象是不可用的
而在实际开发中,可能会存在无用但可达的对象,这些对象不能被 GC 回收,所以也会致使内存泄
露的发生。
回收算法:
1标记—清除算法。标记—清除算法是基础的收集算法,标记和清除阶段的效率不高,
并且清除后回产生大量的不连续空间,这样当程序须要分配大内存对象时,可能没法找到足够的连续空间。
2复制算法.是把内存分红大小相等的两块,每次使用其中一块,当垃圾回收的时候,把存活的对象复制到另外一块上,而后把这块内存整个清理掉。复制算法实现简单,运行效率高,可是因为每次只能使用其中的一半,形成内存的利用率不高。如今的 JVM 用复制方法收集新生代,因为新生代中大部分对象(98%)都是朝生夕死的,因此两块内存的比例不是 1:1(大概是 8:1)
3标记整理算法.标记—整理算法和标记—清除算法同样,可是标记—整理算法不是把存活对象复制到另外一块内存,而是把存活对象往内存的一端移动,而后直接回收边界之外的内存。标记—整理算法提升了内存的利用率,而且它适合在收集对象存活时间较长的老年代
4分代收集.是根据对象的存活时间把内存分为新生代和老年代,根据各个代对象的存活特色,每一个代采用不一样的垃圾回收算法。新生代采用复制算法,老年代采用标记—整理算法。垃圾算法的实现涉及大量的程序细节,并且不一样的虚拟机平台实现的方法也各不相同jvm
引用类型:
1强引用
引用存在就不会回收
2软引用
若是内存空间足够,垃圾回收器就不会回收它,若是内存空间不足了,就会回收这些对象的内存。
3弱引用
弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾
那该类就是无关紧要的对象,由于只要该对象被 gc 扫描到了随时都会把它干掉
4虚引用
虚引用主要用于检测对象是否已经从内存中删除。在任什么时候候均可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。性能
堆,栈
stack:栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS 下,栈的大小是 2M(也有的说是 1M,总之是一个编译时就肯定的常数),若是申请的空间超过栈的剩余空间时,将提示 overflow。所以,能从栈得到的空间较小。
heap:堆是向高地址扩展的数据结构,是不连续的内存区域。这是因为系统是用链表来存储的空闲内存地址的,
天然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。因而可知,
堆得到的空间比较灵活,也比较大spa
java虚拟机的内存结构
堆区:
1.存储的所有是对象,每一个对象都包含一个与之对应的class的信息。(class的目的是获得操做指令)
2.jvm只有一个堆区(heap)被全部线程共享,堆中不存放基本类型和对象引用,只存放对象自己
栈区:
1.每一个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每一个栈中的数据(原始类型和对象引用)都是私有的,其余栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操做指令区(存放操做指令)。
方法区:
1.又叫静态区,跟堆同样,被全部的线程共享。方法区包含全部的class和static变量。
2.方法区中包含的都是在整个程序中永远惟一的元素,如class,static变量。线程
类加载器:一、根类加载器(Bootstrap) --C++写的 ,看不到源码二、扩展类加载器(Extension) 加载位置 :jre\lib\ext三、系统(应用)类加载器(AppClassLoader:System\App) --加载位置 :classpath 中四、自定义加载器(CustomClassLoader:必须继承 ClassLoader)双亲委托机制:4委托到3委托到2委托到1,1没办法加载,再2加载,2没办法加载再3加载...在该机制中,JVM 自带的 Bootstrap 是根加载器,其余的加载器都有且仅有一个父类加载器。当一个类收到了类加载请求,他首先不会尝试本身去加载这个类,而是把这个请求委派给父类去完成,每个层次类加载都是如此,所以全部的加载请求都应该传送到启动类加载器中,只有当父类加载器反馈本身没法完成这个请求的时候(在它的加载路径里找不到这个所须要加载的类),子类加载器才会尝试本身去加载