# 单元测试 **黑盒测试**:不需要写代码,给输入值,看程序是否能够输出期望的值 **白盒测试**:需要写代码.关注程序具体的执行过程 **Junit测试:白盒测试** 步骤: 1. 定义一个测试类(测试用例) > 建议: > > 测试类名:被测试类名Test > > 包名:xxx.xx.xx.test 2. 定义测试方法:可独立运行 > 建议: > > 方法名:test测试方法名 > > 返回值:void > > 参数列表:空参数 3. 给方法加 @Test 4. 导入Junit的依赖 断言:`Assert.function(except,res)` ```java public class ClassNameTest{ // 所有测试方法执行前都会执行该方法 @Before public void init(){} // 所有测试方法执行玩都会执行该方法 @After public void close(){} @Test public void test1(){} @Test public void test2(){} } ``` # 反射 **框架设计的灵魂** 框架:半成品软件. 可以在框架的基础上进行软件开发,简化代码 反射: 将类的各个组成部分封装为其他对象 好处: ``` 1. 在程序的运行过程中,操作这些对象 2. 可以解耦,提高程序的可扩展性 ``` **获取Class对象的方式**: ``` 1. Class.forName("全类民"): 从字节码加载到内存,返回对象 (编译后) 1. 多用于配置文件,将类名定义在配置文件中.读取文件,加载类 2. 类名.class : 通过类名的属性class获取 (加载完成后) 1. 多用于参数传递 3. 对象.getClass() : 使用Object类的getClass方法 (创建对象后) 1. 多用于对象获取字节码 ``` 结论: 同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次. ## class对象功能 获取功能: 1. 获取成员变量们 1. `Field[] getFields()` 2. `Field getField(String name)` 3. `Field[] getDeclaredFields()` 4. `Field getDeclaredFields(String name)` ```java package demo2.reflect; import demo2.domain.Person; import java.lang.reflect.Field; public class ReflectDemo1 { /** 获取Class对象的方式: 1. Class.forName("全类民"): 从字节码加载到内存,返回对象 (编译后) 2. 类名.class : 通过类名的属性class获取 (加载完成后) 3. 对象.getClass() : 使用Object类的getClass方法 (创建对象后) */ public static void main(String[] args) throws Exception { // 0.获取Person的Class对象 Class personClass = Person.class; // 1.获取所有 Public 的成员变量 Field[] fields = personClass.getFields(); for (Field field : fields) { System.out.println(field);//public java.lang.String demo2.domain.Person.a } System.out.println("-----------"); // 2.获取名字为 a 的 Public 的成员变量 Field a = personClass.getField("a"); Person person = new Person(); // 3.获取 a 变量的值 Object o = a.get(person); System.out.println(o);//null // 4.设置 a 变量的值 a.set(person,"a3"); System.out.println(person);//Person{name='null', age=null, a='a3', b='null', c='null', d='null'} // 1. 获取所有 成员变量 Field[] declaredFields = personClass.getDeclaredFields(); for (Field field : declaredFields) { System.out.println(field); } // 2. 获取指定名字的 成员变量 Field d = personClass.getDeclaredField("d"); // 3. 获取 私有变量 d 的值 // d.get(person); // 报错 // 如果设置或访问私有变量,需要暴力反射 d.setAccessible(true); Object o1 = d.get(person); System.out.println(o1); // 4. 设置 变量的值同上 d.set(person,"d3"); System.out.println(person);//Person{name='null', age=null, a='a3', b='null', c='null', d='d3'} } } ``` 2. 获取构造方法们 1. 类似 3. 获取成员方法们 1. 类似 4. 获取类名:`getName()` 构造方法返回的Constructor 方法: ```java class Constructor // 创建对象 T newInstance(Object... initargs) // 创建空参对象也可使用 ClassObject.newInstance() ``` 需求:写一个框架,不能改变该类的任何代码,可以创建任意类的对象,并且执行其中任意方法 实现: ``` 1. 配置文件 2. 反射 ``` ```java package demo2.reflect; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Properties; public class ReflectDemo { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { Properties properties = new Properties(); ClassLoader classLoader = ReflectDemo.class.getClassLoader(); InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties"); properties.load(resourceAsStream); String className = properties.getProperty("className"); String methodName = properties.getProperty("methodName"); // 获取 class对象 Class aClass = Class.forName(className); // 获取 方法 Method method = aClass.getMethod(methodName); // 创建实例对象 Object o = aClass.newInstance(); method.invoke(o); } } ``` # 注解 注释:用文字描述程序,给程序员看的 概念: 说明程序,给计算机看的 概念描述: ``` 1. jdk1.5之后的特性 2. 说明程序的 3. 使用注解: `@注解名称` ``` 作用分类: 1. 编写文档: 生成javadoc文档 2. 代码分析 3. 编译检查: 例如:@Override ## JDK中预定义的一些注解 `@Override` 检测被注解的方法是否继承自父类 `@Deprecated` 该注解标注的内容,表示已过时 `@SuppressWarnings` 压制警告 - 一般传递参数"all" `@SupperssWarnings("all")` ## 自定义注解 格式: ```java 元注解 public @interface 注解名称{ } ``` 本质: 注解本质就是一个接口,该接口默认继承Annocation接口 ```java public interface annocationname extends java.lang.annotation.Annotation{} ``` 属性:接口中的抽象方法 ``` 1. 要求属性的返回值类型: 1. 基本数据类型 2. String 3. 枚举 4. 注解 5. 以上类型的数组 2. 定义的属性在使用是需要被赋值 1. 如果定义属性时,使用default关键字给属性赋默认值 2. 如果只有一个属性,属性名为value,则可以直接写值 3. 数组赋值时,值使用{}包裹,如果只有一个值,{}可省略 4. 注解类型赋值使用@注解名 ``` ### 元注解: 用于描述注解的注解 **@Target: 描述注解能够作用的位置** > 属性为ElementType[] value > > ElemenType为枚举: > > TYPE 类 > > METHOD 方法 > > FIELD 变量 **@Retention: 描述注解被保留的阶段** > 属性为RententionPolicy value > > RententionPolicy为枚举: > > RUNTIME 保留到class字节码文件中,并被jvm读取到 **@Documented:描述注解是否被抽取到api文档中** **@:描述注解是否能被继承** ## 使用注解(获取注解中定义的值) 1. 使用注解取代配置文件来配置程序 2. 测试框架 ## 小结: 1. 以后大多数时候,我们都会使用注解,而不是自定义注解 2. 注解给编译器用,给解析程序用 3. 注解不是程序的一部分,可以理解为一个标签 --- 转载至CSDN博主:[[李唐敏民](https://blog.csdn.net/qq_39041210 "李唐敏民")] 最后修改:2021 年 02 月 18 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏