Java注解
注解也叫标注,用在包,类,变量,方法,参数上,可以通过反射获取标注信息。
可以在编译期间使用,也可以被编译到字节码文件中,运行时生效。
内置注解
@Override java定义好的,直接使用
元注解 修饰注解的注解
@Target(ElementType.METHOD) 注解可以作用在哪些元素上
@Retention(RetentionPolicy.SOURCE) 注解什么时候生效
对象克隆
在一个现有的对象基础上,克隆创建出一个新的对象
浅克隆
在克隆一个对象时,不能将对象中关联的引用类型对象重新创建,只是把引用地址复制过来。
深克隆
在克隆一个对象时,可以将关联对象也一并创建新的对象。
克隆方式:
1、类 实现Cloneable接口,重写Object中的clone方法(在多级关联时,处理起来比较麻烦)
2、使用序列化方式,可以重新创建对象,包含关联的对象
Java设计模式
最早概念是在建筑领域产生的。
后来被引入到软件开发领域。
之前的程序员们,在工作中对某一类问题的解决方式进行总结归纳,一种问题对应着一个模式。
设计模式就是在面向对象的基础上,更加合理的组织类与类之间的关系为什么学习设计模式?
提高编程设计能力,让程序设计更加标准合理,提高开发效率
提高程序的维护性,能够看懂复杂的源码。
UML建模语言
使用特定的图形符号,在设计阶段表示类的结构,以及类与类之间的关系。
类:矩形
接口:圆形
类与类之间的关系
继承
实现(泛化)
依赖 在一个类中的方法中作为局部变量,参数用到了另一个类
关联(根据关系强弱程度,聚合(学校—老师)) 组合关系(头—嘴)
面向对象设计原则
单一职责: 降低类的职责,一个类负责一个功能,耦合度降低
开闭原则: 对修改关闭,对扩展开放。不建议在新加功能时,对原来的代码进行修改,可以通过新增加一个类的方式完成。
对程序进行抽象化设计。
设计出抽象类,接口,不同的功能扩展子类即可。
里氏替换原则
继承
子类继承父类后,尽量不要重写父类的方法,可以新增扩展其它的功能
保证子类功能的正确性,不能让功能修改后,导致程序出错。
依赖倒置
上层依赖于抽象,不依赖于底层实现细节
抽象
具体实现1 具体实现1
接口隔离
接口功能设计时,尽量减少一个接口中有过多的功能,可以细分为多个接口。
迪米特原则
一个对象应该对其它对象有最少的了解
在一个类中,应该尽量少的使用与其没有直接关系的类(非直接朋友)
组合/聚合复用原则
使用继承,为了复用父类中的方法,但是类与类的耦合性高。
可以使用关联/依赖,在一个类中达到复用别的类中的方法。
常用设计模式
单例模式
解决的问题:在一个项目中,一个类只能让它创建一个实例(对象)
实现:把构造方法私有化,在单例类中,向外界提供一个方法访问到唯一的单例对象
饿汉式单例(急切式):静态的成员在类被加载时,就会初始化对象,没有任何的线程安全问题
懒汉式单例:在类加载的时候,不创建对象,在使用时创建,这时,生成对象的数量就需要我们自己来进行控制。
会出现线程安全问题,在多线程访问时,可能会有多个线程同时进行到if,就会创建出多个对象。
懒汉式单例线程安全问题的解决
1.给方法加锁, 可以解决,但是效率低,一次只能有一个线程进入获取
2.给代码块加锁,双重检索+synchronized
使用场景:
Runtime 类
Jdk 中的源码 Runtime 类就是一个单例类,利用 Runtime 类可以启动新的进程或进行相关运行时环境的操作。比如,取得内存空间以及释放垃圾空间。Runtime 类属于典型的单例设计。
//饿汉式单例
private static Runtime currentRuntime = new Runtime();
工厂模式
工厂—>生产对象—>spring
把创建对象的权利反转给spring框架,把创建对象和使用对象分离。
有一个工厂,专门负责创建对象,使用对象时,只需要找对应的工厂
根据我们产生对象的场景,需求的不同,又分为
简单工厂: 抽象出一类产品,实现了/继承了同一个接口/抽象类的子类对象
优点:客户端只负责对象的调用,实现了创建和调用的分离,降低了客户端代码的难度。
缺点:如果增加和减少产品子类,需要修改简单工厂类,违背了开闭原则如果产品子类过多,会导致工厂类非常的庞大,违反了高内聚原则,不利于后期维护.
适用场景:所有的产品子类都有同一个父类(或接口),属于同一个产品系列产品子类比较少的、创建操作比较简单.
工厂方法: 添加了一个抽象工厂,为每个具体的产品都创建一个具体的工厂,符合开闭原则,扩展产品只需要添加一个工厂即可。
但是同一品牌下有多个系列的产品时,此时工厂方法模式,需要创建许多个具体产品工厂,具体工厂数量也会很多。
抽象工厂: 抽象工厂角色,抽象工厂(生成同一品牌,所有系列的产品),具体工厂(一个品牌对应一个具体的工厂),抽象产品,具体产品
原型模式
spring创建bean作用域:
singleton:单例bean 一个类创建一个对象,spring启动时就创建单例对象
prototype:原型的,多例 每次获取时,都会创建一个新的对象
new spring 管理对象 生–额外的增强—死
原生的new对象,如果对象初始化的内容比较多,每次去new,就比较耗时间。
可以使用克隆的方式,去创建对象,提高创建的效率
代理模式
最早在spring框架中AOP提到的,
面向切面编程:在不修改代码的情况下,如果扩展一个新的功能(与业务没有直接联系),不修改代码可以实现。
底层实现:通过一个代理对象来实现对扩展功能的调用。
代理:中介,12306,美团
代理好处:方便,做一些额外操作,隐藏目标对象
代理模式:
静态代理:
一个代理类,只能代理一个接口下的实现类,如果要代理多个接口的实现类,必须重新修改代理类。
动态代理:
在运行时生成代理对象,代理类不需要去实现代理的某一类的接口
动态代理:
jdk代理:要求目标类,必须实现一个接口,在运行时,使用反射,动态获取接口信息,调用某个方法,获取到你要调用的方法,最终执行invoke()方法,将生成的代理对象,调用的方法参数等信息传递过来。这样就实现了代理对象,可以代理任何一个目标类,但是要求所代理的目标类,必须实现一个接口。
Cglib 代理:CGLIB 创建的动态代理对象比JDK 创建的动态代理对象的性能更高,但是 CGLIB 创建代理对象时所花费的时间却比 JDK 多得多。所以对于单例的对象,因为无 需频繁创建对象,用 CGLIB 合适,反之使用 JDK 方式要更为合适一些。同时由于 CGLib 由于是采用动态创建子类的方法,对于 final 修饰的方法无法进行代理。