L*_*L

注解与反射机制

注解与反射

注解【1.可以对程序作出解释;2.可以被其他程序读取】

1. 格式:@注释名

2.分类:

名称 表示 1 表示2 表示3 表示4
内置注解 @Override [表示一个类声明打算重写超类中的另一个方法声明] @Deprecated [表示不鼓励程序员使用这样的元素] @SuppressWarnings [用来抑制编译时的警告信息有参数:all/unchecked/value=("unchecked","deprecation")] 内置注解
元注解 @Taget [用于描述注解的使用范围] @Retention [表示需要什么级别保存注释信息,用于描述注解的生命周期(source<class<runtime)] @Document [说明该注解将被包含在javadoc中] @Inherited[说明子类可以继承父类中的该注解]

3.如何自定义注解:

  • 使用@interface自定义注解,自动继承java.lang.annotation.Annotation接口,格式:public @interface 注释名
  • 其中每一个方法实际上是声明了一个配置参数;方法的名称就是参数的名称;返回值类型【只有class、string、enum】就是参数的类型;可以通过default来声明参数的默认值;如果只有一个参数成员,一般参数名为value;注解元素必须有值,我们定义注解元素时,经常使用空字符串.0作为默认值

反射机制

1.反射的引入:

当编译时不知道类或者对象的具体信息时,我们无法创建对象/操作属性/执行方法,这时就需要使用反射。

2.通过类实现JAVA反射机制:
  • Class类:代表一个类

  • Constructor类:代表类的构造方法

  • Field类:代表类的成员变量(属性)

  • Method类:代表类的成员方法

3.反射的入口【Class类】:

  • 获取一个类的类对象的多种方法:

       1. class.forName()--------------使用的前提:编译/编码时不知道类和对象的具体信息,此时只能使用该方法。
    
           Class clazz = Class.forName("com.ll.Cat"); 
    
       2.类名.class
           Class clazz = Cat.class;
    
       3.对象名.getClass()--------------使用的前提:编译/编码时已经知道类和对象的具体信息
           Cat cat = new Cat();
           Class clazz = cat.getClass();
    
       4.获得父类的类对象
           
           Class clazz = cat.getClass().getSuperclass();
    
       5.仅针对包装类,得到的是包装的基本数据类型的类对象
           Class clazz = Integer.class;
    
  • 类加载过程:
    加载-->{验证-->准备-->解析}(链接)-->初始化

4.利用反射创建对象:

  • 通过无参数构造方法创建对象:

    * 方法1:调用Class的newInstance方法
    
          //1.获取类的完整路径字符串
          String className = "com.ll.Cat";
          //2.根据类的完整路径字符串获取类的对象
          Class clazz = Class.forName(className);
          //3.
          Object o = clazz.newInstance();   //已经不建议使用
    
    * 方法2:调用Constructor的newInstance方法
    
          //1.获取类的完整路径字符串
          String className = "com.ll.Cat";
          //2.根据类的完整路径字符串获取类的对象
          Class clazz = Class.forName(className);
          //3.从类对象中获取无参构造方法
          Constructor con = clazz.getConstructor();
          //4.使用反射调用Constructor的newInstance方法创建对象
          Animal animal = (Animal)con.newInstance();
    
  • 通过无参数构造方法创建对象:

    * 方法1:调用Constructor的newInstance方法
    
          //1.获取类的完整路径字符串
          String className = "com.ll.Cat";
          //2.根据类的完整路径字符串获取类的对象
          Class clazz = Class.forName(className);
          //3.从类对象中获取有参构造方法
          Constructor con = clazz.getDeclaredConstructor(String.class,int.class,String.class);
          con.setAccessible(true);    //突破封装性的限制,即使private也可以调用
          //4.使用反射调用Constructor的newInstance方法创建对象
          Object obj = con.newInstance("迷糊",1,"蓝猫");
    

5.利用反射操作属性:

  • 操作属性----------------实际中使用很少

          * 操作属性
          //1.获取类的完整路径字符串
          String className = "com.ll.Cat";
          //2.根据类的完整路径字符串获取类的对象
          Class clazz = Class.forName(className);
          //3.从类对象中获取有参构造方法
          Object obj = clazz.getConstructor().newInstance();            //相当于 Dog d = new Dog();
          //4.从类对象中获取指定Field
          Field f1 = clazz.getSupperclass().getDeclaredField("nickname");
          //5.使用反射操作属性
          f1.setAccessible(true);    //突破封装性的限制,即使private也可以调用
          f1.set(obj,"迷糊");            //相当于 dog.nickName = "迷糊"
    

6.利用反射执行方法

  • 执行方法

          * 执行方法
          //1.获取类的完整路径字符串
          String className = "com.ll.Cat";
          //2.根据类的完整路径字符串获取类的对象
          Class clazz = Class.forName(className);
          //3.根据反射创建对象
          Constructor con = clazz.getConstructor(String class,int class,String class);
          Object obj = clazz.getConstructor().newInstance();            
          //4.从类对象中获取指定方法
          Method m1 = clazz.geyMethod("shout");
          Method m2 = clazz.geyMethod("add",int class,int class);
          //5.使用反射执行方法
          m1.invoke(obj);
          Object result = m2.invoke(obj,10,20);
    

7.使用反射获取参数类型的泛型信息

  • 认识泛型扩充的数据类型:
类型 例子
parameterized types【参数化类型】 如:List、Map<K,V>的List和Map
type variables【类型变量】 如:List中得T
array types【数组类型】 并不是通常所用的数组String[]、byte[],而是如:List[] ,T[]
WildcardType【通配符类型】 如:List<? extends Number>
  • 获取泛型信息

    //1.得到类对象
    Class clazz = TestGeneric.class;
    //2.获取method
    Method m1 = clazz.getMethod("method1",Map.class,List.class,String.class);
    //3.获取方法参数上的泛型类型:无法获取
    Class<?>[] parameterType = m1.getParameterTypes();
    for(Class parameterType : parameterTypes){
          System.out.println(parameterType);
    }
    //4.获取方法参数上的泛型类型
    Type[] genericParameterType = m1.getGenericParameterType();
    for(Type genericParameterType:generaticParameterTypes){
          Type[] actualTypeArguments = ((ParameterizedType)genericParameterType).getActualTyoeArguments;
          for(Type actualTypeArguments:actualTypeArguments){
                System.out.println("\t\t"+actualTypeArgument);
         } 
    }
    

posted on 2020-12-17 09:03  L*_*L  阅读(57)  评论(0)    收藏  举报