06-Junit单元测试、反射、注解
1、单元测试
1.1、概念
- 单元测试即是对部分代码进行测试
1.2、Junit介绍
- Junit
- Junit是一个Java编程语言的单元测试工具。是一个非常重要的测试工具
 
- Junit特点
- Junit是一个开放源代码的测试工具
- Junit可以很方便地对Java中的方法进行测试,提高测试效率
 
1.3、Junit的使用
1.3.1、Junit的使用基本流程
- Junit的使用基本流程
- 编写测试方法
- 在测试方法上使用@Test
- 运行单元测试方法
 
1.3.2、单元测试方法注意事项
- 单元测试方法的要求
- 必须是public
- 返回值必须是void
- 不能有参数
 
1.3.3、IDEA导入Junit包的流程
- IDEA导入Junit的jar包
1.3.4、断言方法
- 
断言方法 - Assert.assertEquals();
- 如果两者一致,程序继续往下运行
- 如果两者不一致,中断测试,抛出异常信息
 
 
- Assert.assertEquals();
- 
Demo - 
@Test public void test01() { System.out.println("Hello Junit"); System.out.println("运行单元测试成功"); int n = 10 / 2; Assert.assertEquals("你这个运行可能出问题", 5, n); }
 
- 
1.4、单元测试的其他注解
1.4.1、Junit常用注解(Junit 4.xxxx版本)
- @Test
- 表示测试该方法
 
- @Before
- 在每个测试的方法前运行
 
- @After
- 在每个测试的方法后运行
 
- @BeforeClass
- 在所有测试的方法前运行一次
 
- @AfterClass
- 在所有测试的方法后运行一次
 
1.4.2、Junit常用注解(Junit 5.xxxx版本)
- @Test
- 表示测试该方法
 
- @BeforeEach
- 在每个测试的方法前运行
 
- @AfterEach
- 在每个测试的方法后运行
 
- @BeforeAll
- 在所有测试的方法前运行一次
 
- @AfterAll
- 在所有测试的方法后运行一次
 
2、反射
2.1、Class对象介绍
- Class类中会保存什么数据?
- Class对象会保存类中的信息(构造方法,成员方法,成员变量等)
 
- Demo
2.2、反射概述
2.2.1、反射的概念
- 在程序的运行过程中,通过Class对象得到类中的信息(构造方法,成员方法,成员变量等),并操作他们
2.2.2、反射的应用场景
- IDEA的智能提示
- 框架Spring/SpringMVC/Mybatis
2.2.3、反射的作用
- 利用反射调用它类中的属性和方法时,无视修饰符
- 使用反射创建对象,代码更复杂,功能更强大灵活
2.3、三种获取Class对象的方式
- 
类名.class 
- 
对象.getClass() 
- 
Class.forName("类全名") - 该方式使用最灵活(常用),因为类不存在也能通过编译
 
- 
注意事项 - 三种方式获取到的是同一个Class对象,一个类只有一个Class对象
 
- 
Demo - 
public void test01() throws ClassNotFoundException{ // 类名.class Class<Employee> clazz1 = Employee.class; System.out.println(clazz1); // 对象.getClass() Employee emp=new Employee(); Class<?extends Employee> clazz2=emp.getClass(); System.out.println(clazz2); // Class.forName("类全名"); Class<?> clazz3=Class.forName("com.itheima.bean.Employee"); System.out.println(clazz3); }
 
- 
2.4、反射获取方法并使用
2.4.1、反射操作Constructor
- Constructor类的作用
- 表示类中的构造方法
- 如何得到Constructor对象步骤
- 得到Class对象
- 得到Constructor对象
- 如何获取构造器
- getConstructors()
- 得到所有public的构造方法
 
- getConstructor()
- 得到一个public的构造方法
 
- getDeclaredConstructors()
- 获取所有存在的构造方法
 
- getDeclaredConstructor()
- 获取一个存在的构造方法
 
- Constructor类中的方法
- T newInstance(Object... initargs)
- 根据指定的构造器创建对象
 
- public void setAccessible(boolean flag)
- flag为true时,表示取消访问检查,进行暴力反射
 
- 反射得到的构造器可以做什么?
- Object newInstance();
2.4.2、反射操作Method
- 
Method类的作用 - 表示类中的成员方法
 
- 
如何获取Method - getMethods()
- 获取所有public的方法
 
- getMtethod()
- 获取一个public的方法
 
- getDeclaredMethods()
- 获取所有声明的方法
 
- getDeclaredMethod()
- 获取一个声明的方法
 
 
- getMethods()
- 
Method类中的方法 - Object invoke(Object obj, Object... args)
- Object obj:调用方法的对象
- object... args:方法的参数
- Object:返回值
 
 
- Object invoke(Object obj, Object... args)
- 
如何得到Method对象 - 得到Class对象
- 得到Method
 
- 
代码示例 
- 
// 1.得到Class对象 Class<Employee> cls = Employee.class; Employee emp = cls.getConstructor().newInstance(); // 2.得到一个public的方法 Method m1 = cls.getMethod("setName", String.class); // 调用方法 Object ret = m1.invoke(emp, "柳岩");
2.4.3、反射操作Field
- 
Field的作用 - 字段,就是类中的成员变量
 
- 
步骤 - 
1.得到Class对象 
- 
2.得到Field 
- 
代码示例 
- 
// 1.得到Class对象 Class<Employee> cls = Employee.class; Employee emp = cls.newInstance(); // 2.得到Field Field f1 = cls.getDeclaredField("name"); f1.setAccessible(true); // 3.给成员变量赋值 f1.set(emp, "凤姐"); // 4.获取成员变量的值 Object value = f1.get(emp);
 
- 
- 
获取Field - getFields()
- 获取所有public的成员变量
 
- getField()
- 获取一个public的成员变量
 
- getDeclareFields()
- 获取所有声明的成员变量
 
- getDeclareField()
- 获取一个声明的成员变量
 
 
- getFields()
- 
Field类中的方法 - 保存值
- set(Object obj, Object value);
- Object obj:成员变量所在对象
- Object value: 新的值
 
 
- set(Object obj, Object value);
- 获取值
- Object get(Object obj);
- Object obj:成员变量所在对象
- Object:返回成员变量的值
 
 
- Object get(Object obj);
 
- 保存值
2.5、反射案例
- 
步骤 - 通过Properties加载配置文件
- 得到类名和方法名
- 通过类名反射得到Class对象
- 通过Class对象创建一个对象
- 通过Class对象得到方法
- 调用方法
 
- 
代码示例 - 
// 1.通过Properties加载配置文件 Properties pp = new Properties(); pp.load(new FileReader("study_day13\\src\\config.properties")); // {methodname=teach, classname=com.itheima.demo09Reflect.Teacher} System.out.println("pp = " + pp); // 2.得到类名和方法名 String className = pp.getProperty("classname"); String methodName = pp.getProperty("methodname"); // 3.通过类名反射得到Class对象 Class<?> cls = Class.forName(className); // 4.通过Class对象创建一个对象 Object emp = cls.newInstance(); // 5.通过Class对象得到方法 Method method = cls.getMethod(methodName); // 6.调用方法 method.invoke(emp);
 
- 
3、注解
3.1、注解介绍
- 概述
- Annotation表示注解。是JDK1.5的新特性
 
- 注解的主要作用
- 对类进行标注
- 通过注解可以给类增加额外的信息
 
 
- 对类进行标注
3.2、自定义注解
- 
自定义注解格式 - 
@interface 注解名 { 数据类型 属性名(); }
 
- 
- 
使用自定义注解格式 - @注解名(属性1=值1, 属性2=值2)
 
- 
注意事项 - 注解每一个属性都要有值
- 注解的属性可以有默认值,如果不赋值就使用默认值
- 一个位置不能搞两个一个的注解
 
3.3、注解的属性类型
- 注解只能保存简单的数据
- 1.基本数据类型
- 2.String,枚举,Class,注解
- 3.以上类型的一位数组
 
- 注意事项
- 自定义类型不行,如Employee,ArrayList,Integer等等
 
3.4、自定义注解的属性介绍
- 当注解中只有一个属性
- 并且属性名是value
- 在使用注解时,可以省略value属性名
 
 
- 并且属性名是value
3.5、元注解
3.5.1、概述
- 修饰注解的注解
3.5.2、@Target元注解
- 作用
- 限制注解的使用位置
 
- 常用值
- @Target(ElementType.TYPE) // 可以放在类或接口上
- @Target(ElementType.CONSTRUCTOR) // 可以放在构造方法
- @Target(ElementType.METHOD) // 可以放在成员方法上
- @Target(ElementType.FIELD) // 可以放在成员变量上
- @Target(ElementType.LOCAL_VARIABLE) //可以放在局部变量上
 
3.5.3、@Retention元注解
- 作用
- 限制注解的生命周期(让注解能后活到什么时候)
![]() 
 
- 常用值
- @Retention(RetentionPolicy.SOURCE)
- 注解在源代码阶段有,后面就没有了
 
- @Retention(RetentionPolicy.ClASS)
- 注解在字节码阶段有,后面就没有了
 
- @Retention(RetentionPolicy.RUNTIME)
- 注解在运行时阶段也在
 
 
- @Retention(RetentionPolicy.SOURCE)
3.6、注解解析
- 概念
- 使用Java技术获得注解上数据的过程称为注解解析
 
- AnnotatedElement方法
- T getAnnotation(Class annotationClass)
- 根据注解类型获得对应注解对象
 
- Annotation[] getAnnotations()
- 获得当前对象上使用的所有注解
 
- boolean isAnnotationPresent(Class annotationClass)
- 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则返回false
 
 
- T getAnnotation(Class annotationClass)
- 如何解析注解
- 通过反射来解析注解,原则注解在谁头上就用谁来解析
 
3.7、模拟Junit自带的@Test注解
- 步骤
- 1.定义MyTest注解
- 2.定义普通类并包含多个方法,在一些方法头上配@MyTest注解
- 使用反射得到类中的所有Method
- 遍历得到每个Method,如果Method上有MyTest,就运行这个方法
 
 
                     
                    
                 
                    
                



 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号