• junit单元测试

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

  • ​ 步骤:

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

    2. 定义测试方法:可以独立运行

    3. 给方法加注解(@Test)(需要加上注解才可以独立运行方法)

    4. 导入Junit的依赖环境

    5. 判定结果:

      ​ 红色:测试失败

      ​ 绿色:测试成功

      ​ 一般我们使用断言来处理结果Asser.assertEquals(期望的结果,实际结果);

      补充:@Before:

      ​ 修饰的方法会在测试方法之前被自动执行

      ​ @After:

      ​ 修饰的方法会在测试方法执行之后被执行

  • package cn.itcast.junit;
    //计算器类
    public class Calculator {
    public int add(int a,int b){
    return a+b;
    } public int sub(int a ,int b){
    return a-b;
    }
    }
  • package cn.itcast.test;
    //需要导入junit包,才可以独立运行方法
    import cn.itcast.junit.Calculator;
    import org.junit.After;
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test; /**
    * @Author: A
    * @Date: 2019/5/30 10:33
    * @Version 1.0
    * 测试add方法
    */
    public class CalculatorTest {
    /*
    * 初始化方法
    * 用于资源申请,所有测试方法在执行之前都会先执行此方法
    * */
    @Before
    public void init(){
    System.out.println("init......");
    }
    /*
    * 释放资源方法
    * 在所有测试方法执行完毕后,都会执行该方法
    * */
    @After
    public void close(){
    System.out.println("close...");
    }
    @Test
    public void testAdd(){
    //System.out.println("我被执行了");
    //创建计算器对象
    Calculator c = new Calculator();
    //调用add方法
    int result = c.add(1,2);
    System.out.println(result);
    //断言
    //我期望的结果是2,真实结果不是,断言失败
    //程序控制台出现红色
    Assert.assertEquals(3,result);
    }
    }
    //init......
    //3
    //close...
  • 反射:框架设计的灵魂

    • 框架:半成品软件。可以在框架的基础上进行软件开发,简化代码
    • 反射:将类的各个组成部分封装为其他对象,这就是反射机制(组成部分包括成员方法,成员变量,构造方法等)
    • 反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
  • 获取Class对象的方式:
    1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
    2. 类名.class:通过类名的属性class获取
    3. 对象.getClass()
  • //Class.forName("全类名")
    //多用于配置文件
    Class cls1 = Class.forName("cn.itcast.domain.Person"); //类名.class
    //多用于参数的传递
    Class cls2 = Person.class; //对象.getClass()
    //多用于对象的获取字节码的方式
    Person p = new Person();
    Class cls3 = p.getClass();
  • Field:成员变量

  • ​ 常用方法

  • ​ 1.设置值 void set (Object obj ,Object value)

  • ​ 2.获取值 get (Object obj)参数需要传递对象,

  • ​ 3.忽略访问权限修饰符的安全检查 setAccessible(true)

  • 获取成员变量

  • package cn.itcast.reflect;
    //接下来要写的几个获取功能的类都与此类有关联 public class Person {
    private String name;
    private int age;
    public String a;
    protected String b;
    String c;
    private String d; public Person() {
    } public Person(String name, int age) {
    this.name = name;
    this.age = age;
    } public String getName() {
    return name;
    } public int getAge() {
    return age;
    } public void setName(String name) {
    this.name = name;
    } public void setAge(int age) {
    this.age = age;
    } @Override
    public String toString() {
    return "Person{" +
    "name='" + name + '\'' +
    ", age=" + age +
    ", a='" + a + '\'' +
    ", b='" + b + '\'' +
    ", c='" + c + '\'' +
    ", d='" + d + '\'' +
    '}';
    }
    public void eat(){
    System.out.println("eat....");
    }
    public void eat(String food){
    System.out.println("eat...."+food);
    }
    }
  • package cn.itcast.reflect;
    
    import java.lang.reflect.Field;
    
    public class ReflectDemo {
    public static void main(String[] args) throws Exception{ //获取Person的Class对象
    Class personClass = Person.class;
    //调用Class对象的方法getFields获取成员变量,返回的是Field[] 成员变量的数组
    //获取所有的public 修饰的成员变量
    Field[] fields = personClass.getFields();
    //对fields遍历,获取每一个public修饰的成员变量
    for(Field field :fields){
    System.out.println(field);
    }
    //获取指定名称的public 修饰的成员变量
    //Field getField(String name)
    Field a =personClass.getField("a");
    //获取成员变量a的值,需要使用get(Object obj)方法,需要传递对象参数
    Person p = new Person();
    Object value = a.get(p);
    System.out.println(value);//null
    //设置成员变量a的值
    a.set(p,"张三");
    System.out.println(p);
    System.out.println("====================");
    //获取所有的成员变量,不考虑修饰符
    Field[] declaredFields = personClass.getDeclaredFields();
    for(Field dec :declaredFields){
    System.out.println(dec);
    }
    //获取指定名称的成员变量
    //Field getDeclaredField(String name)
    Field d =personClass.getDeclaredField("d");
    //忽略访问权限的修饰符的安全检查
    d.setAccessible(true);
    //获取成员变量的值,需要传递对象参数
    Object value2 = d.get(p);
    System.out.println(value2);
    }
    }
  • Constructor:构造方法

  • ​ 创建对象: T new Instance(Oject... initargs)参数是对象构造方法的参数类型

  • ​ 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

  • 获取构造方法

  • package cn.itcast.reflect;
    
    import java.io.ObjectStreamClass;
    import java.lang.reflect.Constructor; public class ReflectDemo1 {
    public static void main(String[] args) throws Exception{
    //获取Person的Class对象
    Class personclass = Person.class;
    //获取Class对象的构造方fa
    Constructor c =personclass.getConstructor(String.class,int.class);
    System.out.println(c);
    //构造方法用来创建对象的,
    //Constructor 有个方法newInstance可以创建对象
    Object person = c.newInstance("张三",22);
    System.out.println(person); //使用空参数构造器创建对象
    Constructor c1 =personclass.getConstructor();
    System.out.println(c1);
    Object person1 = c1.newInstance();
    System.out.println(person1);
    //可以通过Class对象方法直接创建空参数的构造器
    Object o = personclass.newInstance();
    System.out.println(o);
    }
    }
  • 获取成员方法与类
  • ​ Method:方法对象

  • ​ 执行方法:Object invoke(Object obj,Object...args) 需要传递真实的对象与参数列表

  • 获取类名:

  • ​ String getName()

  • package cn.itcast.reflect;
    
    import java.lang.reflect.Method;
    
    public class ReflectDemo2 {
    public static void main(String[] args) throws Exception{
    //获取Person的Class对象,返回的是一个Class类
    Class personClass = Person.class;
    //获取指定的Public成员方法
    //需要传递方法的名称,返回值是Method类
    Method eat_Method =personClass.getMethod("eat");
    Person p = new Person();
    eat_Method.invoke(p);//eat....
    //获取有参数的成员方法,需要传递方法名称
    Method eat_method2 =personClass.getMethod("eat",String.class);
    //获取到方法,就要执行方法
    //执行方法,需要传递对象和参数
    eat_method2.invoke(p,"饭"); //获取所有public 方法
    Method[] allMethod = personClass.getMethods();
    for(Method method : allMethod){
    //获取方法的名称getName();
    System.out.println(method.getName());
    System.out.println(method);
    } //获取类名
    String className=personClass.getName();
    System.out.println(className);//cn.itcast.reflect.Person
    }
    }
  • 案例

  • 需求:写一个框架,不能改变给类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意的方法

  • 步骤:

    1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
    2. 在程序中加载读取配置文件
    3. 使用反射技术来加载类文件进内存
    4. 创建对象
    5. 执行方法
  • package cn.itcast.reflect;
    
    import java.io.InputStream;
    import java.lang.reflect.Method;
    import java.util.Properties; public class ReflectTest {
    public static void main(String[] args) throws Exception{
    //加载配置文件
    //创建Properties对象
    Properties pro = new Properties();
    //获得Class字节码文件
    Class c = ReflectTest.class;
    //通过字节码文件c下的方法getClassLoader 可以获得一个类加载器
    ClassLoader cl = c.getClassLoader();
    //可以通过Classloader类下的方法“getResourceAsStream​(String name)”可以找到需要的配置文件获得一个字节输入流
    //传递的参数为要加载的文件,获取字节输入流
    InputStream is= cl.getResourceAsStream("pro1.properties");
    //Properties 类的方法 “load​(InputStream inStream);”需要一个字节输入流的参数
    //可以使用Properties集合中的方法load,把硬盘中保存的文件,读取到集合中使用
    pro.load(is);//配置文件加载完成 //获取配置文件中定义的数据
    String className = pro.getProperty("className");
    String methodName=pro.getProperty("methodName"); //加载该类进内存,
    Class cls= Class.forName(className);
    //创建对象,可以通过Class中的方法newInstance来获取
    Object obj= cls.newInstance();
    //获取指定的成员方法
    Method method = cls.getMethod(methodName);
    //执行方法,需要传递对象obj
    method.invoke(obj);
    }
    }
    //似懂非懂……懂非懂…………非懂………………懂…………
  • 注解

  • 定义:注解(Annotation),也叫元数据,一种代码级别的说明,他是JDK1.5及以后版本引入的一个特性,与类,接口枚举是在同一个层次,他可以声明在包,类,字段,方法,局部变量,方法参数等的前面,用来对这些元素进行说明,注释

  • 作用分类:

    1. 编写文档:通过代码里标识符的注解生产文档
    2. 代码分析:通过代码里标识的注解对代码进行分析
    3. 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查
  • JDK中预定的一些注解

    1. @Override :检测被该注解标注的方法是否是继承自父类的

    2. @Deprecated: 该注解标注的内容,表示已过世

    3. @SuppressWarnings:压制警告

  • 自定义注解

  • 格式:

    ​ 元注解:

    ​ public @interface 注解名称{}

    本质:注解本质上就是一个接口,该接口默认继承Annotation接口

    属性:接口中可以定义成员方法

    ​ 属性的返回值类型

    ​ 1.基本数据类 2.String 3.枚举 4.注解 5.以上类型的数组

    定义了属性,在使用时要给属性赋值

    	1. 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不就行属性的赋值
    1. 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可

      3. 数组赋值时,值使用{}包裹,如果数组中只有一个值则{}省略
  • 元注解:用于描述注解的注解
  • @Target:描述注解能够作用的位置

    ​ ElementType取值:TYPE:可以作用于类上; METHOD:可以作用于方法上 FIELD:可以作用于成员变量上

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

    ​ @Retention(RetentionPolicy,RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到

    @Documented:描述注解是否被抽取到api文档中

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

  • package cn.itcast.reflect;
    public @interface Myanno2 {
    }
  • package cn.itcast.reflect;
    //枚举类的定义
    public enum Person2 {
    p1,p2;
    }
  • package cn.itcast.reflect;
    
    public @interface Myanno {
    //注解可以返回的类型
    // 1.基本数据类 2.String 3.枚举 4.注解 5.以上类型的数组
    int show1();
    public abstract String show2() default "张三";
    public abstract Person2 per();
    Myanno2 anno2();
    //String[] strs();*/ }
  • package cn.itcast.reflect;
    //String类型的返回值已经被default修饰了,可以不用对属性进行赋值
    @Myanno(show1=1,per=Person2.p1,anno2=@Myanno2)
    public class Worker {
    }
  • 注解案例练习

  • package cn.itcast.reflect;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Check {
    }
  • package cn.itcast.reflect;
    
    public class Calculator {
    //加法
    @Check
    public void add(){
    System.out.println("1+0="+(1+0));
    }
    //减法
    @Check
    public void sub(){
    System.out.println("1-0="+(1-0));
    }
    //乘法
    @Check
    public void mul(){
    System.out.println("1*0="+(1*0));
    }
    //除法
    @Check
    public void div(){
    System.out.println("1/0="+(1/0));
    }
    public void show(){
    System.out.println("永无bug");
    }
    }
  • package cn.itcast.reflect;
    
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.lang.reflect.Method; /**
    * 简单的测试框架
    * 当主方法执行后,会自动检测所有方法(加了Check注解的方法)
    */ public class TestCheck {
    public static void main(String[] args) throws IOException {
    //创建计算器对象
    Calculator c = new Calculator();
    //获取字节码文件
    Class cls = c.getClass();
    //获取所有方法
    Method[] methods = cls.getMethods();
    int number =0;//出现异常的次数
    BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt")); for(Method method : methods){
    //判断方法上是否有Check注解
    if(method.isAnnotationPresent(Check.class)){
    //有,执行
    try{
    method.invoke(c);
    }catch (Exception e){
    //捕获异常
    //记录到文件中
    number++;
    bw.write("方法出异常了");
    bw.newLine();
    bw.write("异常名称:"+e.getCause());
    bw.newLine();
    bw.write("异常的原因"+e.getCause().getMessage());
    bw.newLine();
    bw.write("--------------------");
    bw.newLine();
    }
    bw.write("本次测试一共出现"+number+"次异常");
    bw.flush();
    }
    }
    }
    }
/*
*本次测试一共出现0次异常本次测试一共出现0次异常方法出异常了
异常名称:java.lang.ArithmeticException: / by zero
异常的原因/ by zero
--------------------
本次测试一共出现1次异常本次测试一共出现1次异常
/

最新文章

  1. 一个简易的四则运算单元...(15.12.15 BUG更新)
  2. eclipse 闪退
  3. C++11 删除链表重复数值
  4. IOS AutoLayout 遍历修改约束
  5. Linux 信号
  6. 炼狱—Bug集中营
  7. mysql的四种隔离级别
  8. 数组排序、递归——(Java学习笔记二)
  9. 微软Visual Studio "14" CTP 2 发布
  10. virualbox 安装 otter 必备软件
  11. 洛谷 [p1196] 银河英雄传说
  12. c语言第五次作业--函数
  13. python 二维数组遍历
  14. C++ STL next_permutation(快速排列组合)
  15. iterable与iterator
  16. Rk3288 双屏异显单触摸
  17. js中 给json对象添加属性和json数组添加元素
  18. logback-spring.xml 博客分享
  19. css position[转
  20. HDFS架构详解-非官档

热门文章

  1. WPF窗口最大化
  2. OpenCV中使用SVM简介
  3. @SafeVarargs 使用说明
  4. 翻译:A Tutorial on the Device Tree (Zynq) -- Part III
  5. delete from inner join
  6. yum报错File "/usr/bin/yum", line 30 except KeyboardInterrupt, e:
  7. 简说 call() 、apply() 、bind()
  8. C++11 std::function、std::bind和lambda表达式
  9. rails使用mysql数据库
  10. File.Copy的时候Could not find a part of the path