Java 基础进阶 Junit单元测试 反射 及 注解
初步了解反射以及注解的原理,在框架中会大量接触反射,后期项目会接触到制作自定义注解
Junit单元测试
概述
- JUnit是一个Java语言的单元测试
- 单元:一个方法就是一个单元
- 测试: 测方法中的代码逻辑是否正确
作用
- 替代main方法
一个类只能有一个main方法 如果有N个功能要单独测试的话,需要写N个类由N个main方法进行不同的测试
如果使用单元测试会让程序功能的测试更加简单
实现方式
- JUnit的使用步骤
- 1.导JUnit单元测试的jar包 (idea开发工具已经集成了junit的jar包)
- 2.在类中要测试的方法上添加 @Test
- 3.测试执行
- JUnit的细节整理
- 1.方法必须得是公共的
- 2.返回值必须得是void
- 3.方法不能有任何的参数
- 常见注解
- @Test: 单元方法测试
- @Before:在每个测试方法之前都会运行一次
- @After:在每个测试方法运行以后运行的方法
- 了解注解
-
- 静态方法可以使用
- @BeforeClass
- @AfterClass
ps:会在 @Before之前执行 会在 @After之后执行
反射
概述
-
反射是一种行为,利用该行为可以在程序运行过程中对类进行解剖并操作类中的方法,属性,构造方法成员
类:
构造方法
成员方法
成员变量一个类的执行流程:
hello.java —编译–>hello.class —加载内存–>jvm创建了Class对象用来记录数据—>运行
Student.java —编译–>Student.class—加载内存–>jvm创建了Class对象用来记录数据—>运行
Person.java —编译–>Person.class—加载内存–>jvm创建了Class对象用来记录数据—>运行如何拿到类中的数据:
Class(字节码对象): 接收一切类的字节码文件
Constructor(构造器对象): 接收类中的一切构造方法
Method(方法对象): 接收类中的一切成员方法
Field(变量对象): 接收类中的一切成员变量
作用
- 通过反射可以获取到每个类的字节码对象,拿到其中的构造方法,成员方法和成员变量
ps应用场景: 后期我们要学的ssm框架底层用到了很多的反射行为,为了后面能够更加理解框架,这里需要同学们对反射机制熟练化
核心实现
获取字节码对象的三种方式(面试题–重要)
- 方式1:通过类名.class获取
- 方式2:通过Object类的成员方法getClass()方法获取
- 方式3:通过Class.forName(“全限定名”)方法获取
ps全限定名: 就是包名 + 类名
相关API(Class, Constructor,Method,Field)
-
Class对象相关方法
-
String getName() 获取全限定名,包含 包名+类名
-
String getSimpleName() 获得简单类名,只是类名,没有包名
-
Object newInstance() 创建此 Class 对象所表示的类的一个实例。要求:类必须有公共的无参数构造方法
-
-
操作构造方法(Constructor)
-
Constructor getConstructor(Class… parameterTypes)
根据参数类型获取构造方法对象,只能获得public修饰的构造方法。 -
Constructor getDeclaredConstructor(Class… parameterTypes)
根据参数类型获取构造方法对象,包括private修饰的构造方法。 -
T newInstance(Object… initargs)
根据构造器中的指定参数创建对象。 -
void setAccessible(true)
暴力反射,设置为可以直接访问私有类型的构造方法 -
Constructor[] getConstructors() (了解)
获取所有的public修饰的构造方法 -
Constructor[] getDeclaredConstructors() (了解)
获取所有构造方法,包括privat修饰的
-
-
操作方法(Method)
Method是方法类,类中的每一个方法都是Method的对象,通过Method对象可以调用方法。
- Method getMethod("方法名", 方法的参数类型... 类型)
根据方法名和参数类型获得一个方法对象,只能是获取public修饰的
- Method getDeclaredMethod("方法名", 方法的参数类型... 类型)
根据方法名和参数类型获得一个方法对象,包括private修饰的
- Object invoke(Object obj, Object... args) 核心方法
使用反射的方式让一个方法执行
obj : 要执行该方法的对象
args : 方法运行过程中需要的参数
- void setAccessible(boolean flag)
暴力反射,设置为true可以直接调用私有修饰的成员方法
- Method[] getMethods() (了解)
获取所有的public修饰的成员方法,包括父类中。
- Method[] getDeclaredMethods() (了解)
获取当前类中所有的方法,包含私有的,不包括父类中。
- 操作属性(Field)
Field是属性类,类中的每一个属性(成员变量)都是Field的对象,通过Field对象可以给对应的成员变量赋值和取 值。
- Field getField(String name)
根据属性名获得属性对象,只能获取public修饰的
- Field getDeclaredField(String name)
根据属性名获得属性对象,包括private修饰的
- Field[] getFields()(了解)
获取所有的public修饰的属性对象,返回数组。
- Field[] getDeclaredFields()(了解)
获取所有的属性对象,包括private修饰的,返回数组
- getType() (了解)
获取字段类型
- set(字段所属的对象,要赋的值)
给字段赋值的,如果是私有的还是要先暴力破解
反射明确的点:框架
1 获取字节码对象的方式
2 如何根据字节码对象获取各种构造器让各种构造器创建对象
3 如何根据字节码对象获取各种方法让各种方法执行
4 如何根据字节码对象获取各种字段给各种字段赋值
注解
概述:
-
在java中由一个 @+一堆英文单词组成的集合 就是注解
-
它可以声明在类、字段、方法、局部变量、方法参数上等,用来对程序进行限制说明的
注释:给程序员看的
注解:给程序去看的 声明不同的注解可以让程序做不同的功能
注解的学习明确:
1 明确java或者框架提供的注解都有什么功能
2 明确提供的注解能定义在哪个位置上 (类上 字段上 方法上 局部变量上)
jdk中的注解
- @Override
限制该方法是重写的方法 - @Deprecated
声明该方法不推荐使用
扩展:自定义注解(理解)
-
格式:
- public @interface 注解名称{
类型 属性名();
…
}
注解本质上就是一个特殊的接口
注解中的方法叫做属性.
- public @interface 注解名称{
-
属性:
-
基本类型 (byte,short,int,long,float,double,boolean,char)
-
String
-
Class
-
Annotation
-
以上类型的一维数组
常见注解
-
@英文字符 底层:要不就是没属性 要不属性全部有默认值
@英文字符(属性名1=属性值1,属性名2 = 属性值2) 底层:注解设置属性 没有给默认值 需要使用的时候设置
@英文字符(“abcd”) 底层:注解的属性中只有一个 且名称叫value
- 注意事项:
-
注解一旦有了属性,使用注解时,必须给属性赋值
-
注解名称如果为value,那么属性名称可以省去不写
自定义注解小结:
1.自定义注解格式: public @interface 注解名称{}
2.注解可以使用在类,方法,接口,成员变量,局部变量…
3.注解中的方法不叫方法,叫属性
4.当注解中有属性时,使用该注解时,必须给注解中的属性赋值
5.当只给value属性赋值时,value属性名可以省去不写
-
元注解
定义在注解之上的注解被称为元注解
- @Target 定义该注解作用在什么上面 常用值为:
- METHOD:方法
- TYPE:类 接口
- FIELD:字段
- @Retention 定义该注解保留到那个代码阶段(存活时期) 值为:
- SOURCE:注解只在源码上保留
- CLASS:注解在源码和字节码上保留
- RUNTIME:注解在所有的阶段都保留 (常用)
解析注解
反射机制
- method.isAnnotationPresent(注解.class):判断方法上是否有指定的注解
- method.getAnnotation(注解.class);获取方法上指定的注解
案例2-自定@MyTest注解,实现单元测试的功能
需求分析:
定义一个类,在类中提供多个方法,在部分方法上添加自定义的 @MyTest 注解,让带有@MyTest的注解方法执行.
技术分析:
自定义注解 @MyTest
步骤分析:
1.定义@MyTest注解,声明该注解只能使用在方法上,生成注解的存活时期为运行时期
2.定义一个类,在类中提供多个方法,在部分方法上添加MyTest注解
3.让带有@MyTest的方法执行