Javase-day23-Junit单元测试、反射、注解

一、Junit单元测试

测试的分类

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

在这里插入图片描述
Juint单元测试是白盒测试

1、Junit的使用

使用步骤:

  1. 定义一个测试类(测试用例)
    建议:测试类名——被测试的类名Test,如:CalculatorTest;包名——cn.itcast.test
  2. 定义测试方法:可以独立运行
    建议:方法名——test+测试的方法名,如:testAdd();返回值:void;参数列表:空参
  3. 给方法加@Test
  4. 导入Junit依赖环境

判定结果:

  • 控制台显示红色:表示失败
  • 绿色:成功
  • 一般我们会使用断言操作来处理结果
    例如:Assert.assertEquals(期望的结果,运算的结果);

2、补充

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

不管测试有没有出错,被这两个注解修饰的方法,一定会执行了
在这里插入图片描述

二、反射

反射是框架设计的灵魂。框架是半成品软件,可以在框架的基础上进行软件开发,简化编码。

1、反射的概念

将类的各个组成部分封装为其他对象,这就是反射机制(将成员变量封装为Filed对象,将构造方法封装为Constructor对象,将成员方法封装为Method对象)

在这里插入图片描述

2、反射的好处

  • 可以在程序运行过程中,操作这些对象
  • 可以解耦,提高程序的可扩展性

3、获取Class类对象的三种方式

  1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
    多用于配置文件,将类名定义在配置文件中。读取文件,加载类

  2. 类名.class:通过类名的属性class获取
    多用于参数的传递

  3. 对象.getClass():getClass()方法是在Object类中,所有对象都可以用这个方法
    多用于对象的获取字节码的方式

结论:
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过上面的那种方式获取的Class对象都是同一个

4、Class类对象的功能

获取功能:

1.获取成员变量们

  • Filed[] getFields():获取所有public修饰的成员变量

  • Filed[] getField(String name):获取指定的public修饰的成员变量

  • Filed[] getDeclaredFileds():获取所有的成员变量, 不考虑修饰符

  • Filed[] getDeclaredFiled(String name):获取指定的成员变量,不考虑修饰符

Field(成员变量),对成员变量可进行的操作:
1.设置值:void set(Object obj, Object value)
2.获取值:get(Object obj)
3.忽略访问权限修饰符的安全检查:方法setAccessible(true):暴力反射
在这里插入图片描述

2.获取构造方法们

  • Constructor<?>[] getConstructors()

  • Constructor<T>[] getConstructor(类<?>... parameterTypes)

  • Constructor<?>[] getDeclaredConstructors()

  • Constructor<T>[] getDeclaredConstructor(类<?>... parameterTypes)

Constructor(构造方法),对构造方法可进行操作:

  • 创建对象:
    T newInstance(Object… initargs);
    如果使用了空参数的构造方法创建对象,操作可以省略:直接可以使用Class对象的newInstance方法

在这里插入图片描述

3.获取成员方法们

  • Method[] getMethods()

  • Method[] getMethod(String name, 类<?>... parameterTypes)

  • Method[] getDeclaredMethods()

  • Method[] getDeclaredMethod(String name, 类<?>... parameterTypes)

Method(方法对象),操作有:

  • 执行方法:Object invoke(Object obj, Object… args)
  • 获取方法的名称:String getName——获取方法名

在这里插入图片描述

4.获取类名

  • String getName()

5、反射的案例

需求:写一个“框架”,在不能改变该类任何代码的前提下,可以创建任意类的对象,并执行其中任意方法

实现:1.配置文件;2.反射

实现步骤:

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

配置文件(pro.properties):全类名可以该为cn.itcast.damain.Person,方法名可以改为eat

className=cn.itcast.damain.Student
methodName=sleep

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

// 用反射创建任意类的对象,到时候只用改配置文件内容,不用改代码
public class ReflectTest {
    public static void main(String[] args) throws Exception {

        // 1.加载配置文件
          // 1.1创建Properties对象
        Properties pro = new Properties();
          // 1.2加载配置文件,转换为一个集合
            // 1.2.1获取class目录下的配置文件
        ClassLoader classLoader = ReflectTest.class.getClassLoader();  //class文件的类加载器
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        pro.load(is);

        // 2.获取配置文件中定义的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        // 3.加载该类进入内存
        Class cls = Class.forName(className);
        // 4.创建对象
        Object obj = cls.newInstance();
        // 5.获取方法对象
        Method method = cls.getMethod(methodName);
        // 6.执行方法
        method.invoke(obj);
    }
}

改配置文件,比改程序的代码更好。
如果在配置文件里面有全类名,那这个地方用的就是反射机制。

三、注解

注解的概念: JDK1.5之后的新特性,用来说明程序的

使用注解:@注解名称

作用分类:
①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
②代码分析:通过代码里标识的注解对代码进行分析【使用反射】
③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】

1、JDK中预定义的一些注解

  • @Override:检测被该注解标注的方法是否是继承自父类(接口)的
  • @Deprecated:该注解标注的内容,表示已过时
  • @SuppressWarnings:压制警告
      一般传递参数all @SuppressWarnings(“all”)
@SuppressWarnings("all")
// 压制了该类的所有警告
public class AnnoDemo2 {
    @Override
    public String toString() {
        return super.toString();
    }

    @Deprecated
    public void show1() {
        // 有缺陷
    }

    public void show2() {
        // 代替show1方法
    }
}

2、自定义注解

注解定义的格式:
  元注解
  public @interface 注解名称{
    属性列表;
  }

注解的本质: 注解本质上就是一个接口,该接口默认继承Annotation接口
  public interface MyAnno extends java.lang.annotation.Annotation { }

注解的属性: [注解的属性]就是注解这个接口中的[抽象方法]
   要求:
      1.属性的返回值类型:
         基本数据类型(四类八种),String类型,枚举类型,注解类型,以上类型的数组
      
       2.定义了属性,在使用时需要给属性赋值
         1. 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
         2. 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。
         3. 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略

元注解: 描述注解的注解
    @Target:描述【注解能够作用的位置】
     其中枚举ElementType有三个取值要记住:
          TYPE:可以作用于类上
          METHOD:可以作用于方法上
          FIELD:可以作用于成员变量上
    
    @Retention:描述【注解被保留的阶段(三个阶段)】
         @Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到 class字节码文件中,并被 JVM 读取到
    
    @Documented:描述注解是否被抽取到 API 文档中
    
    @Inherited:描述注解是否被子类继承

3、在程序使用(解析)注解:获取注解中定义的属性值

  1. 获取注解定义的位置的对象 (Class,Method,Field)

  2. 获取指定的注解

getAnnotation(Class)  // 其实就是在内存中生成了一个该注解接口的子类实现对象

public class ProImpl implements Pro{
    public String className(){
        return "cn.itcast.annotation.Demo1";
    }
    public String methodName(){
        return "show";
    }
}
  1. 调用注解中的抽象方法获取配置的属性值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值