Junit、反射、注解

Junit单元测试

测试分类:

  • 黑盒测试:不需要写代码,测试程序对输入的值时候能输出期望的值

  • 白盒测试:需要写代码,关注程序的具体流程(Junit属于这一种)

Junit使用

步骤:

  1. 定义一个测试类(测试用例)

    建议

    • 测试类名为:被测试的类+Test,例如CalculatorTest
    • 包名:xxx.xxx.xx.test,例如cn.taoyyz.test
  2. 定义测试方法(可以独立运行)

    建议

    • 方法名:test+测试的方法名,例如testAdd()
    • 返回值:void
    • 参数列表:空参
  3. 给方法加注解:@Test,需要解决报错把依赖添加到路径

  4. 判定结果:一般使用断言 Assert类来处理结果

    image-20210719114838150 绿色代表成功,否则失败

    image-20210719115133805
  5. 可以通过多个@Test注解进行多个测试

补充

  • @Before:修饰的方法会在@Test测试的方法之前执行
  • @After:修饰的方法会在@Test测试的方法之后执行

反射

反射是框架设计的灵魂

  • 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码。

概念

将类的各个组成部分封装为其他对象,这就是反射机制。

image-20210719134708584

  • 好处:
    1. 可以在程序运行过程中,操作这些对象。
    2. 可以解耦,提高程序的可扩展性。

获取Class对象的方式:

1.Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
多用于配置文件,将类名定义在配置文件中.读取文件,加载类
2.类名.class:通过类名的属性class获取
多用于参数的传递
3.对象.getClass():继承于Object类
多用于对象的获取字节码的方式

同一个.class字节码文件在一次程序运行过程中只被加载一次,不论通过哪种方式获取的对象都是同一个

Class对象的功能

获取功能:

1.获取成员变量们

  • Field getField(String name) 通过指定的成员变量名获取public字段

  • Field[] getFields() 返回此Class对象表示的类或接口的所有可访问public字段

  • Field[] getDeclaredFields() 返回由此Class对象表示的类或接口声明的所有字段的Filed数组

  • Field getDeclaredField( String name) 返回此Class对象表示的类或接口的指定声明字段。

    操作Field:成员变量

    1.设置值

    void set(Object obj,Object value)

    2.获取值

    Object get(Object obj)

    3.忽略访问权限修饰符的安全检查(暴力反射)

    setAccessible(boolean flag)

    2.获取构造方法们

  • Constructor getConstructor( Class<?>… parameterTypes)返回此Class对象表示的类的指定公共构造方法

  • Constructor<?>[] getConstructors() 返回此Class对象表示的类的所有公共构造函数

  • Constructor getDeclaredConstructor(Class<?>… parameterTypes) 返回此Class对象表示的类或接口的指定构造函数。

  • Constructor<?>[] getDeclaredConstructors() 返回此Class对象表示的类声明的所有构造函数。

    操作Constructor:构造器

    1.利用构造器创建对象

    T newInstance(Object... initargs)

    2.利用空参构造创建对象时,无需获取Class对象的构造器再调用newInstance方法,可以直接利用Class对象自带的newInstance方法。

    3.获取成员方法们

  • Method getMethod(String name,Class<?>… parameterTypes) 此Class对象表示的类或接口的指定公共成员方法。

  • Method[] getMethods() 此Class对象表示的类或接口的所有公共方法,包括由类或接口声明的方法以及从超类和超接口继承的方法。

  • Method getDeclaredMethod(String name,Class<?>… parameterTypes) 返回此Class对象表示的类或接口的指定声明方法。

  • Method[] getDeclaredMethods() 返回此Class对象表示的类或接口的所有声明方法,包括公共、受保护、默认(包)访问和私有方法,但不包括继承的方法。

    操作Method:成员方法

    1.执行方法

    Object invoke(Object obj,Object... args)如果要执行的方法没有参数列表,则第二个参数可以省略

    2.获取方法名称

    String getName()返回方法的名称

4.获取类名

  • String getName() 返回该实体(类,接口,数组类,基本类型,或void)的全类名(包括包路径名)

  • String getSimpleName() 返回简单类名(不包括包路径)

案例需求

写一个”框架”,不能改变任何代码的情况下,可以创建任意对象,执行任意的方法

实现:

1.配置文件
2.反射

步骤:

1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
2.在程序中加载读取配置文件
3.使用反射技术来加载类文件进内存
4.创建对象
5.执行方法

注解

概念

区别于”注释”:
1.注释是用来说明程序的一些文字,给程序员看的
2.注解是用来说明程序的,给计算机看的
注解:从JDK5开始,Java增加对注解的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。

概念描述

  • JDK1.5之后的新特性

  • 用来说明程序

  • 使用注解:@注解名称

    作用分类

  • 编写文档:通过代码里标识的注解生成文档【生成javadoc文档】

    ​ 例如在javadoc文档注释中可以利用一些注解例如:@author指定作者,利用@since指定自从…

  • 代码分析:通过代码里标识的注解对代码进行分析【使用反射】

  • 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】

JDK中预定义的一些注解

  • @Override:检测被该注解标注的方法时候是继承于父类(接口)的
  • @Deprecated:将该注解标注的内容表示为“已过时”
  • @SuppressWarnings:压制警告,需要传递参数String[] value,一般传递”all”

自定义注解

格式

public @interface 注解名称 {
​ 属性列表…;
}

  • 元注解:用于描述注解的注解

    • @Target:描述直接能够作用的位置

      • 参数ElementType[] value()掌握3个取值:

        1.ElementType.TYPE 表示能作用于类上

        2.ElementType.METHOD 表示能作用于方法上

        3.ElementType.FIELD 表示能作用于成员变量上

    • @Retention:描述注解被保留的阶段

      • 参数RetentionPolicy value() 一般使用RetentionPolicy.RUNTIME 表示当前注解会保留到class字节码文件中,并被JVM读取到
    • @Documented:描述注解是否能被抽取到API文档中

    • @Inherited:描述注解是否被子类继承

以上的“元注解”是用于修饰Annotation的,也就是打在注解上的注解

本质

  • public interface MyAnnotation extends java.lang.annotation.Annotation { }

  • 属性:接口中可以定义的成员方法,可以看做抽象方法

    要求:

    1.属性的返回值类型:

    • 基本数据类型

    • String

    • 枚举

    • 注解

    • 以上类型的数组

    2.使用了含有属性的注解时必须给属性赋值

    • 定义的属性如果指定了default值,那就可以不赋值
    • 如果只有一个属性需要赋值,并且属性的名称为value,那么可以把(value=12)简写为(12)
    • 枚举类型赋值为color = Color.red
    • 注解类型赋值为anno = @MyAnno
    • 数组类型赋值为strArr = {“a”,”b”,”c”},当数组只有一个值时,可以省略{大括号}

在程序中使用(解析)注解

1.获取该类的字节码对象:类名.class 返回一个Class

2.获取指定的注解:调用该字节码对象的getAnnotation(Class annotationClass) 返回一个注解对象

  • 打在一个class类上的注解可以通过getAnnotation()得到。同样的,打在一个方法上的注解也可以通过getAnnotation得到,所以对于一个Method对象,也可以调用getAnnotation()方法获取注解
  • 对于获取到的注解对象,可以直接调用它里面属性(或者是说抽象方法)得到打注解时指定的值

3.也可以调用getAnnotations()返回所有的注解到一个Annotation[ ]数组里。