Javaweb_day01_基础加强

2018-11-26
今日内容
1.Junit单元测试
2.反射
3.注解
 
Junit单元测试
测试分类:
1.黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值。
2.白盒测试:需要写代码的,关注程序具体的执行流程。
 
Junit使用:白盒测试
步骤:
1.定义一个测试类(测试用例)
  建议:
  测试类名:被测试的类名Test        CalculatorTest
  包名:xxx.xxx.xx.test         cn.itcast.test
2.定义测试方法:可以独立运行
  建议:
  方法名:test测试的方法名         testAdd()  
  返回值:void
  参数列表:空参
 
注意:
1.测试方法的权限修饰符必须是public。
2.测试方法的返回值必须是void。
3.测试方法的参数列表必须是空。
3. 给方法加@Test(执行测试的代码)
4. 导入junit依赖环境
 
判定结果:
红色:失败 绿色:成功
一般我们会使用断言操作来处理结果
Assert.assertEquals(期望值,实际值);
 
补充:
@Before:修饰的方法会在测试方法之前被自动执行
@After:修饰的方法会在测试方法执行之后自动被执行
 
反射:框架设计的灵魂
框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
反射:将类的各个组成部分封装为其他对象,这就是反射机制
反射的好处:
1.可以在程序运行过程中,操作这些对象。
2.可以解耦,降低了程序的耦合性,提高程序的可扩展性。
 
java代码的三个阶段图解:
获取Class对象的方式:
1.Class.forName("全路径类名"):Class类的静态方法forName,将字节码文件加载进内存,返回Class对象
  * 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
2.类名.class:通过类名的属性class获取
  * 多用于参数的传递
3.对象.getClass():getClass()方法在Object类中定义着。
  * 多用于对象的获取字节码的方式
 
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
 
Class对象功能:
获取功能:
1.获取成员变量们
Field[] getFields() 获取所有public修饰的成员变量
Field getField(String name)   获取指定名称的public修饰的成员变量
 
Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name) 获取指定名称的public/private修饰的成员变量
2.获取构造方法们
Constructor<?>[] getConstructors()  获取所有public修饰的构造方法
Constructor<T> getConstructor(Class<?>... parameterTypes)  获取指定的public修饰的构造方法
 
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)  获取指定的public/private修饰的构造方法
Constructor<?>[] getDeclaredConstructors() 获取所有的public/private修饰的构造方法
3.获取成员方法们:
Method[] getMethods()  获取所有的public修饰的成员方法
Method getMethod(String name, Class<?>... parameterTypes)  获取指定的public修饰的成员方法 (最常用)
 
Method[] getDeclaredMethods()  获取所有的public/private修饰的成员方法
Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获取指定的public/private修饰的成员方法
 
4.获取全路径类名    
String getName() 
 
Field:成员变量
操作:
1.设置值 void set(Object obj, Object value)
2.获取值 object get(Object obj)
3.忽略访问权限修饰符的安全检查 void setAccessible(true):暴力反射
 
Constructor:构造方法
创建对象:T newInstance(Object... initargs)
如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
 
Method:方法对象
执行方法:Object invoke(Object obj, Object... args) (被执行方法的对象,方法参数值)
获取方法名称:String getName():获取方法名
 
反射案例:
类加载器ClassLoader:
获取:Class对象的getClassLoader()方法进行获取
使用(结合Properties):
InputStream is = 加载器对象.getReasourceAsStream("src目录下的文件")
Properties prop = new Properties();
prop.load(is);
注解:
1.注释与注解:
注释:不参与代码的编译,给程序员看的
注解:参与代码的编译,给计算机看的
2.JDK预定义注解:
@Override:检查重写的方法
@Deprecated:标注当前方法已过时
@SuppressWarnings:压制警告(SuppressWarnings("all") 压制所有警告)
3.自定义注解:
格式:public @interface 注解名称{}
本质:就是一个接口,默认继承Annotation接口
public interface MyAnno extends java.lang.annotation.Annotation {}
属性:
介绍:相当于抽象方法
属性的返回值类型:基本类型、String、枚举、注解、以上类型的数组
定义了属性,使用时需要给属性赋值:
1.定义属性时,通过default关键字设置了默认值,则使用时可以不赋值
2.如果属性只有一个,并且名称是value,则赋值时,value可以不写
3.数组赋值时,使用{}包裹,如果只有一个值,{}可以省略不写
4.元注解:
概念:用来描述注解的注解
@Target:描述注解作用的位置
ElementType.TYPE:作用在类上
ElementType.METHOD:作用在方法上
ElementType.FIELD:作用在成员变量上
 
@Retention:描述注解被保留的阶段
Retentionpolicy.SOURCE:保留在源码阶段
Retentionpolicy.CLASS:保留在字节码文件阶段
Retentionpolicy.RUNTIME:保留在JVM运行阶段
 
@Documented:描述注解是否被抽取到API文档中
 
@Inherited:描述注解是否被子类继承
5.解析注解:
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";
                        }
                    }

 

3.获取注解的属性值
 
6.注解综合案例
1.获取测试类的Class对象
2.通过Class对象获取所有的方法
3.循环遍历所有方法,获取每个方法
4.判断当前方法是否含有指定注解
5.执行含有注解的方法,出现异常时,将异常信息写入到本地文件
代码展示:
Check注解:

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 { }

 

 Calculator计算器类:
public class Calculator {

    //加法
    @Check
    public void add(){
        String str = null;
        str.toString();
        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...");
    }
}

 TestCheck测试框架类:

 

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
 * 简单的测试框架
 *
 * 当主方法执行后,会自动自行被检测的所有方法(加了Check注解的方法),判断方法是否有异常,记录到文件中
 */
public class TestCheck {
    public static void main(String[] args) throws IOException {
        //1.创建计算器对象
        Calculator c = new Calculator();
        //2.获取字节码文件对象
        Class cls = c.getClass();
        //3.获取所有方法
        Method[] methods = cls.getMethods();

        int number = 0;//出现异常的次数
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));

        for (Method method : methods) {
            //4.判断方法上是否有Check注解
            if(method.isAnnotationPresent(Check.class)){
                //5.有,执行
                try {
                    method.invoke(c);
                } catch (Exception e) {
                    //6.捕获异常

                    //记录到文件中
                    number ++;

                    bw.write(method.getName()+ " 方法出异常了");
                    bw.newLine();
                    bw.write("异常的名称:" + e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("异常的原因:"+e.getCause().getMessage());
                    bw.newLine();
                    bw.write("--------------------------");
                    bw.newLine();

                }
            }
        }
        bw.write("本次测试一共出现 "+number+" 次异常");
        bw.flush();
        bw.close();

    }
}

 小结:    

1. 以后大多数时候,我们会使用注解,而不是自定义注解

  2. 注解给谁用?     

   1. 编译器     

   2. 给解析程序用   

3. 注解不是程序的一部分,可以理解为注解就是一个标签

猜你喜欢

转载自www.cnblogs.com/xcs842590060/p/10023765.html