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,就运行这个方法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?