Java中测试和注解概念

Junit 单元测试(白盒)

  • 测试分类

    • 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值
    • 白盒测试:需要写代码,关注程序具体的执行流程
  • 步骤:

    1. 定义一个测试类(测试用例)
    // 建议
    测试类名: 被测试的类名Test
    包名: xxx.xxx.xx.test
    
    1. 定义测试方法:可以独立运行
    // 建议
    方法名: test测试的方法名
    返回值: void
    参数列表: 空参
    
    1. 给方法加 @Test
    2. 导入 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...");
    }
    

反射

  • 框架设计的灵魂

    • 框架: 半成品软件, 可以在框架的基础上进行软件开发, 简化编码
    • 反射: 将类的各个组成部分封装为其它对象, 这就是反射机制
  • 好处

    1. 可以在程序运行过程中, 操作这些对象
    2. 可以解耦, 提高程序的可扩展性
  • 获取 Class 对象的方式

    1. Source 源代码阶段
      • Class.forName("全类名"):将字节码文件加载进内存, 返回Class对象多用于配置文件, 将类名定义在配置文件中. 读取文件, 加载类
    2. Class 类对象阶段
      • 类名.class :通过类名的属性 class 获取,多用于参数的传递
    3. 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);
    }
    
  • Class 对象功能

    1. 获取成员变量们
      • 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);
    
    1. 获取构造方法们
      • 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);
    
    1. 获取成员方法们
      • 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,"饭");
    
    1. 获取类名
      • String getName()
    // 获取类名
    String className = personClass.getName();
    System.out.println(className);
    

注解

  • 说明程序的,给计算机看

  • @注解名称

  • 预定义的注解

    扫描二维码关注公众号,回复: 11238873 查看本文章
    • @Override:检测被该注解标注的方法是否是继承自父类(接口)的
    • @Deprecated:该注解标注的内容, 表示已过时
    • @SuppressWarnings:压制警告
      • 一般传递参数 all
      • @SuppressWarnings(“all”)
  • 自定义注解

    • 格式(元注解)

      • public @interface 注解名称{}
    • 本质:注解本质上就是一个接口, 该接口默认继承 Annotation 接口

      • public interface 注解名称 extends java.lang.annotation.Annotation{}
    • 属性:接口中可以定义的成员方法

      • 要求

        1. 属性的返回值类型

          1. 基本数据类型
          2. String
          3. 枚举
          4. 注解
          5. 以上类型的数组
          int show1();
          String show2();
          
          Person per();
          MyAnno anno2();
          
          String[] strs();
          
        2. 定义了属性, 在使用时需赋值

          1. 默认赋值
            • String name() default "张三";
          2. 使用时赋值
            • @MyAnno(value=12,per=Person.P1,anno2=@MyAnno2,strs={"abc","bbb})
          3. 注意
            1. 如果定义属性时, 使用 default 关键字给属性默认初始化值, 则使用注解时, 可以不进行属性的赋值
            2. 如果只有一个属性需要赋值, 并且属性的名称是 value, 则 value 可以省略, 直接定义值即可
            3. 数组赋值时, 值使用{}包裹; 如果数组中只有一个值, 则{}可以省略
    • 元注解(用于描述注解的注解)

      • @Target:描述注解能够作用的位置
        • ElementType 取值
          • TYPE:可以作用于类上
          • METHOD:可以作用于方法上
          • FIELD:可以作用于成员变量上
        • @Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
      • @Retention:描述注解被保留的阶段
        • @Retention(RetentionPolicy.RUNTIME):当前被描述的注解, 会保留到 class 字节码文件中, 并被 JVM 读取到
      • @Documented:描述注解是否被抽取到 api 文档中
      • @Inherited:描述注解是否被子类继承
  • 在程序中使用(解析)注解

    // 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();
    

猜你喜欢

转载自blog.csdn.net/mryjf/article/details/106234953