欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

笔记-JavaWeb学习之旅

程序员文章站 2022-03-06 21:38:10
junit单元测试 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值 2. 白盒测试:需要些代码,关注程序具体的执行流程 Junit使用: 白盒测试 ​ 步骤: 1. 定义一个测试类(测试用例) 2. 定义测试方法:可以独立运行 3. 给方法加注解(@Test)(需要加上注解才可以 ......
  • 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可以省略,直接定义值即可
      1. 数组赋值时,值使用{}包裹,如果数组中只有一个值则{}省略
  • 元注解:用于描述注解的注解
  • @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次异常
/