单元测试
为什么单元测试要叫单元测试
单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此,单元测试就是针对Java方法的测试。
如何实现单元测试
-
必须导入Junit框架的jar包
-
定义的测试方法必须是无参数无返回值,且公开的方法。
-
测试方法使用@Test注解标记。
Junit4.x.x 常用注解
@Before 常用于初始化资源
@After 常用于释放资源
反射
反射有什么用
反射,可以让我们在类运行的时候,直接获取类的信息和类的成分,如构造器对象、成员变量对象、成员方法对象
反射的原理是什么
.java 文件编译后会变成 .class 字节码文件,这时获得这个 class 文件,就可以得到解析出class 的所有成分
什么是Class 类对象
Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI。
这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
也就是说:
- Class类也是类的一种,只是名字和class关键字高度相似。Java是大小写敏感的语言。
- Class类的对象内容是你创建的类的类型信息,比如你创建一个shapes类,那么,Java会生成一个内容是shapes的Class类的对象
- Class类的对象不能像普通类一样,以 new shapes() 的方式创建,它的对象只能由JVM创建,因为这个类没有public构造函数
- Class类的作用是运行时提供或获得某个对象的类型信息,和C++中的typeid()函数类似。这些信息也可用于反射。
反射的第一步是获取 Class 对象,那么如何获取
方式一:Class c1 = Class.forName(“全类名”);//静态初始化
方式二:Class c2 = 类名.class//不初始化
方式三:Class c3 = 对象.getClass();//静态初始化 + 非静态初始化
利用反射获取构造器的 API
利用反射得到的构造器可以用来干什么
创建对象
public newInstance(Object… initargs)
如果是非public的构造器,需要打开权限(暴力反射),然后再创建对象
setAccessible(boolean)
利用反射获得成员变量的 API
利用反射获得的成员变量可以做什么
用于取值、赋值
如果某成员变量是非public的,需要打开权限(暴力反射),然后再取值、赋值
setAccessible(boolean)
利用反射获得成员方法的API
利用反射获得的成员方法对象可以做什么
可以触发执行这个方法
如果某成员方法是非public的,需要打开权限(暴力反射),然后再触发执行
setAccessible(boolean)
反射为何可以给约定了泛型的集合存入其他类型的元素
- 编译成Class文件进入运行阶段的时候,泛型会自动擦除。
- 反射是作用在运行时的技术,此时已经不存在泛型了
反射的作用
- 可以在运行时获得一个类的全部成分,进行操作
- 可以破坏封装性(无视访问权限,直接获取成分)
- 可以破坏泛型的约束性(泛型只在编译结算会约束类型,编译完,class文件中就会进行类型擦除,运行时,直接获得集合元素,可以无视类型,添加任意元素)
- 用于做高级框架(无视类的成员类型、有哪几个成员,直接遍历操作)
注解
自定义注解如何生效
注解只是有标记作用。
自定义一个注解,然后利用反射获取对象上方的注解,如果为自定义的注解,就进行业务操作。
如何自定义注解
属性值就是想要用户输入的参数
还需要加上元注解
value 属性有什么特别之处
value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写!!
但是如果有多个属性, 且多个属性没有默认值,那么value名称是不能省略的
元注解有哪些
常用的是 @Target 和 @Retention
@Target 说明自定义的注解可以用在什么对象上
- TYPE,类,接口
- FIELD, 成员变量
- METHOD, 成员方法
- PARAMETER, 方法参数
- CONSTRUCTOR, 构造器
- LOCAL_VARIABLE, 局部变量
@Retention 注解说明自定义注解的生命周期
- SOURCE: 注解只作用在源码阶段,生成的字节码文件中不存在
- CLASS: 注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值.
- RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)
注解如何解析,注解输入的参数如何取出
- 注解@Target 在什么成分上,就先利用反射获得那个成分对象。比如注解作用成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解。
- 获得对象上的注解,使用 getDeclaredAnnotation
- 获得注解的属性值,并进行业务处理
动态代理
什么是动态代理
为一个目标对象,创建代理对象,代理对象的业务逻辑包括了目标对象,并且在那基础上进行功能增强。
静态代理和动态代理如何实现
静态代理
比如原本是 A.class AImpl.class 中的 a() 方法,我想在 a() 方法前后增加一些记录时间的功能,则可以使用静态代理
- 直接实现 A.class
- 将 AImpl() 作为成员变量
- 实现 a(),代码为
{
记录时间;
aimpl.a();
记录时间;
}
将方法包裹起来
动态代理
当扩展 A 接口中的方法时,代理类也需要更改,这样很不方便,于是衍生出动态代理,利用反射,遍历接口中的每个方法,并增强每个方法
具体示例:
https://www.yisu.com/zixun/770726.html
动态代理在实际项目中有什么用
可以用于记录日志,监控性能,权限控制,缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 ),事务管理 (调用方法前开启事务, 调用方法后提交关闭事务 )