一、反射

  1. 定义

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

   三个步骤:source源代码阶段类加载器——Class类对象阶段创建对象——Runtime运行时阶段

  

 

 

  2.获取class对象的方式

   ⑴class.forName("全类名") :将字节码文件加载进内存,返回class对象

    多用于配置文件,将类名定义在配置文件中,读取文件,加载

   ⑵类名.class :通过类名的属性class获取

    多用于参数的传递

   ⑶对象.getClass() :getClass方法在object类中定义着

    多用于对象的获取字节码的方式

  *在同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,无论通过那种方式获得的class对象都是同一个。

  3. 获取功能

   ⑴获取成员变量们

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

    File   getField(String name) :获取指定名称的public修饰 的成员变量

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

    File   getDeclaredField(String name) :获取指定名称的成员变量,不考虑修饰符

    Filed:成员变量操作      

        暴力反射 d.setAccessible(true)

        设置值: void set(Object obj,object value)

        获取值:get(Object  obj)

 

          ⑵ 获取构造方法们

    Constructor<?>[]    getDeclaredConstructors()

    Constructor<T>    getDeclaredConstructor(类<?>.... parameterTypes)//(string.class,int.class)

    Constructor:构造方法

        创建对象 newInstance(object..initargs)//(张三,18)

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

   ⑶获取成员方法们

    Method[]  getDeclaredMethods()

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

    Method方法对象

        执行方法,object invoke(object obj ,object...args)

        获取方法名:String getName 

   ⑷获取类名

    String geiName()

 4.“框架测试 ”

  public class Test {
     public static void main(String[] args) throws Exception {
        //可以创建任意类的对象,可以执行任意方法

        /*
            前提:不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法
         */
       /*  Person p = new Person();
          p.eat();*/
        /*
        Student stu = new Student();
        stu.sleep();*/


        //1.加载配置文件
        //1.1创建Properties对象
        Properties pro = new Properties();
        //1.2加载配置文件,转换为一个集合
        //1.2.1获取class目录下的配置文件
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        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);
         }
   }

  ----------------------------------------------------------------------------

  //pro.properties

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

二、注解

  1.概念: 说明程序的,给计算机看的,元数据,是对包,类,方法等元素的说明

      javadoc

      @注解名称

      @param 参数

      @return 返回值

  2.作用分类

   @编写文档:通过代码里标注的注解文档【生成doc文档】   

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

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

  3.JDK 预定义注解

    @override  检测该注解标注的方法是否是继承父类接口的

    @Deprecated  该注解标注的内容,表示已过时

    @suppressWarnings  压制警告的

   4.自定义注解(javap  反编译)

   格式: 

      元注解

      public @interface 注解名称{

        属性列表

        }

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

      public interface MyAnno extends java.lang.annotation.Annotation

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

       要求:

          1.属性的返回值类型(只有基本数据类型,String,枚举,注解以上类型的数组)

          2.在使用的时候必须要赋值,(default 默认赋值,如果只有一个属性需要赋值且名字为VALUE,则赋值可以省略VALUE)

          @MyAnno(value=12,per=Person.p1,anno2=@MyAnno2,str={'a','b'})

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

         @Target:描述注解能够作用的位置

              TYPE:作用于类上

              METHOD:可以作用于方法上

              FIELD:可以作用于成员变量上

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

           SOURCE 

           CLASS

           RUNTIME:RetentionPolicy.Runtime

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

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

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

     .1获取注解定义的位置的对象(class,method,filed)

     .2获取指定的注解

       getAnnotation(class) 

     .3调用注解中抽象方法获取配置的属性值

    @Pro(className = "cn.itcast.annotation.Demo1",methodName = "show")
    public class ReflectTest {
          public static void main(String[] args) throws Exception {

          /*
              前提:不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法
           */
          //1.解析注解
          //1.1获取该类的字节码文件对象
          Class<ReflectTest> reflectTestClass = ReflectTest.class;
          //2.获取上边的注解对象
          //其实就是在内存中生成了一个该注解接口的子类实现对象
          /*
              public class ProImpl implements Pro{
                  public String className(){
                      return "cn.itcast.annotation.Demo1";
                  }
                  public String methodName(){
                      return "show";
                  }
              }
     */
          Pro an = reflectTestClass.getAnnotation(Pro.class);
          //3.调用注解对象中定义的抽象方法,获取返回值
          String className = an.className();
          String methodName = an.methodName();
          System.out.println(className);
          System.out.println(methodName);

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

  6.注解小案例

   /*简单的测试框架

   * 当主方法执行后,会自动自行被检测的的所有方法(加了Check注解的方法),判断方法是否有异常,记录到文件中去。

     public class TestCheck{

      //1.创建计算器对象

      Calculator c=new Calculator();

      //2. 获取字节码文件对象

      Class cls=c.getClass();

      //3.获取所有方法

      Method [] methods=cls.getMethods();

      int number =0;//出现异常的次数

      BufferedWreiter bw=new BufferedWriter(new FileWriter("bug.txt"));

      for (Method method: Methods){

        //4.判断方法上是否有Check注解

        if(method.isAnnotationPresent(check.class)){

         //5.有,执行

          try{

             method.invoke();

          }catch(Exception e){

           //6.捕获异常

           //记录到文件中 

             number++;

              bw,wite(method.getName() +"方法出异常了");

              bw.newLine();

              bw.write("异常的名称"+e.getCause().getClass().getSimpleName());

              bw.newLine();

              bw.write("异常的原因"+e.getCause().getMessage());                    

              bw.newLine();

           }

        }

        bw.wrtie(“本次测试一共出现”+number+“异常”);

        bw.flush();

        bw.close();

      }   

    }

   

 

         

    

posted on 2019-11-14 14:39  大超人  阅读(183)  评论(0编辑  收藏  举报