Java中测试和注解概念
程序员文章站
2022-05-29 15:55:13
...
Junit 单元测试(白盒)
-
测试分类
- 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值
- 白盒测试:需要写代码,关注程序具体的执行流程
-
步骤:
- 定义一个测试类(测试用例)
// 建议 测试类名: 被测试的类名Test 包名: xxx.xxx.xx.test
- 定义测试方法:可以独立运行
// 建议 方法名: test测试的方法名 返回值: void 参数列表: 空参
- 给方法加 @Test
- 导入 Junit 依赖环境
-
判定(红色失败,绿色成功)
- 一般使用断言操作来处理结果
Assert.assertEquals(期望的结果,传递的结果);
@Test public void testSub(){ Calculator c = new Calculator(); int result = c.sub(1,2); Assert.assertEquals(-1,result); }
-
补充
- @Before:修饰的方法会在测试方法之前被自动执行
- @After:修饰的方法会在测试方法执行之后自动被执行
/** * 初始化方法: * 用于资源申请,所有测试方法在执行之前都会先执行该方法 */ @Before public void init(){ System.out.println("init..."); } /** * 释放资源方法: * 在所有测试方法执行完后,都会自动执行该方法 */ @After public void close(){ System.out.println("close..."); }
反射
-
框架设计的灵魂
- 框架: 半成品软件, 可以在框架的基础上进行软件开发, 简化编码
- 反射: 将类的各个组成部分封装为其它对象, 这就是反射机制
-
好处
- 可以在程序运行过程中, 操作这些对象
- 可以解耦, 提高程序的可扩展性
-
获取 Class 对象的方式
- Source 源代码阶段
-
Class.forName("全类名")
:将字节码文件加载进内存, 返回Class对象多用于配置文件, 将类名定义在配置文件中. 读取文件, 加载类
-
- Class 类对象阶段
-
类名.class
:通过类名的属性 class 获取,多用于参数的传递
-
- Runtime 运行时阶段
-
对象.getClass()
: getClass()方法在 Object 类中定义着,多用于对象的获取字节码的方式
-
- 结论:同一个字节码文件(*.class)在一次程序运行过程中, 只会被加载一次,不论通过哪一种方式获取的 Class 对象都是同一个
public static void main(String[] args) throws Exception { // 1.Class.forNamae("全类名") Class cls1 = Class.forName("cn.itcast.domain.Person"); // 2.类名.class Class cls2 = Person.class; // 3.对象.getClass() Person p = new Person(); Class cls3 = p.getClass(); System.out.println(cls3); }
- Source 源代码阶段
-
Class 对象功能
- 获取成员变量们
-
Field[] getFields()
:获取所有 public 修饰的成员变量 -
Field getField(String name)
: -
Field[] getDeclaredFields()
:获取所有的成员变量, 不考虑修饰符 -
Field getDeclaredFields(String name)
:不能访问私有, 但可以暴力反射
-
Class personClass = Person.class; // (1)------------------------------ Field[] fields = personClass.getFields(); // (2)------------------------------ Field a = personClass.getField("a"); Person p = new Person(); // 获取成员变量 a 的值 Object value = a.get(p); sout(value); // 设置 a 的值 a.set(p,"张三"); sout(p); // (3)------------------------------ Field[] declaredFields = person.getDeclaredFields(); // foreach... // (4)------------------------------ Field d = person.getDeclaredFields("d"); d.setAccessible(true); //忽略访问权限修饰符的安全检查, 暴力反射 Object value2 = d.get(p); sout(value2);
- 获取构造方法们
Constructor<?>[] getConstructors()
Constructor<T> getConstructors(类<?>... parameterTypes)
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
Constructor<?>[] getDeclaredConstructors()
/* 创建对象 T newInstance(Object... initargs) 如果使用空参数构造方法创建对象, 操作可以简化: Class 对象的 newInstance 方法 */ // Constructor<T> getConstructor(类<?>... parameterTypes) Constructor constructor = personClass.getConstructor(String.class, int.class); System.out.println(constructor); // 创建对象 Object person = constructor.newInstance("张三", 23); System.out.println(person); Object o = personClass.newInstance(); System.out.println(o);
- 获取成员方法们
Method[] getMethods()
Method getMethod(String name, 类<?>... parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, 类<?>... parameterTypes)
/* 执行方法 Object invoke(Object obj, Object...args) 获取方法名称 String getName */ // 获取指定名称的方法 Method eat_method = personClass.getMethod("eat"); Person p = new Person(); // 执行方法 无参 eat_method.invoke(p); Method ea_method2 = personClass.getMethod("eat",String.class); // 执行方法 有参 eat_method2.invoke(p,"饭");
- 获取类名
String getName()
// 获取类名 String className = personClass.getName(); System.out.println(className);
- 获取成员变量们
注解
-
说明程序的,给计算机看
-
@注解名称
-
预定义的注解
- @Override:检测被该注解标注的方法是否是继承自父类(接口)的
- @Deprecated:该注解标注的内容, 表示已过时
- @SuppressWarnings:压制警告
- 一般传递参数 all
- @SuppressWarnings(“all”)
-
自定义注解
-
格式(元注解)
public @interface 注解名称{}
-
本质:注解本质上就是一个接口, 该接口默认继承 Annotation 接口
public interface 注解名称 extends java.lang.annotation.Annotation{}
-
属性:接口中可以定义的成员方法
-
要求
-
属性的返回值类型
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型的数组
int show1(); String show2(); Person per(); MyAnno anno2(); String[] strs();
-
定义了属性, 在使用时需赋值
- 默认赋值
String name() default "张三";
- 使用时赋值
@MyAnno(value=12,per=Person.P1,[email protected],strs={"abc","bbb})
- 注意
- 如果定义属性时, 使用 default 关键字给属性默认初始化值, 则使用注解时, 可以不进行属性的赋值
- 如果只有一个属性需要赋值, 并且属性的名称是 value, 则 value 可以省略, 直接定义值即可
- 数组赋值时, 值使用{}包裹; 如果数组中只有一个值, 则{}可以省略
- 默认赋值
-
-
-
元注解(用于描述注解的注解)
- @Target:描述注解能够作用的位置
- ElementType 取值
- TYPE:可以作用于类上
- METHOD:可以作用于方法上
- FIELD:可以作用于成员变量上
@Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
- ElementType 取值
- @Retention:描述注解被保留的阶段
-
@Retention(RetentionPolicy.RUNTIME)
:当前被描述的注解, 会保留到 class 字节码文件中, 并被 JVM 读取到
-
- @Documented:描述注解是否被抽取到 api 文档中
- @Inherited:描述注解是否被子类继承
- @Target:描述注解能够作用的位置
-
-
在程序中使用(解析)注解
// 1.获取注解定义的位置对象 (Class,Method,Field) // 2.获取指定的注解 getAnnotation(Class) // 其实就是在内存中生成了一个该注解接口的子类实现对象 public class ProImpl implements Pro{ public String className(){ return "cn.xxx.annotation.Demo1"; } public String methodName(){ return "show"; } } // 3.调用注解中的抽象方法获取配置的属性值 // 1.解析注解 // 1.1 获取该类的字节码文件对象 Class<RefkectTest> reflectTestClass = ReflectTest.class; // 2.获取上边的注解对象 // 其实就是在内存中生成了一个该注解接口的子类实现对象 Pro an = reflectTestClass.getAnnotation(Pro.class); // 3.调用注解对象中定义的抽象方法,获取返回值 String className = an.className();
上一篇: HTML&CSS知识点
下一篇: 3.表的创建