zoukankan      html  css  js  c++  java
  • java反射

    java反射
    一个、Java Reflection
         Reflection(反射)它是要动态语言的关键。反射在运行时通过同意程序的方式Reflection API获得内幕信息,无论是什么样的,性及方法
    ①Java反射机制提供的功能
        在执行时推断随意一个对象所属的类
        在执行时构造随意一个类的对象
        在执行时推断随意一个类所具有的成员变量和方法
        在执行时调用随意一个对象的成员变量和方法
        生成动态代理
    ②反射相关的主要API:
        java.lang.Class:代表一个类
        java.lang.reflect.Method:代表类的方法
        java.lang.reflect.Field:代表类的成员变量
        java.lang.reflect.Constructor:代表类的构造方法
    二、Class 类
    ①Class本身也是一个类
        java.lang.Class:是反射的源头。


        我们创建了一个类,通过编译(javac.exe),生成相应的.class文件。之后我们使用java.exe载入(JVM的类载入器完毕的)
        此.class文件,此.class文件载入到内存以后。就是一个执行时类,存在在缓存区。那么这个执行时类本身就是一个Class的实例!


        1.每个执行时类仅仅载入一次。
        2.有了Class的实例以后,我们才干够进行例如以下的操作:
            1)*创建相应的执行时类的对象
            2)获取相应的执行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...)
            3)*调用相应的执行时类的指定的结构(属性、方法、构造器)
            4)反射的应用:动态代理
    ②Class类的经常用法
        static Class  forName(String name) :载入并返回指定类名 name 的 Class 对象
        Object newInstance() :调用缺省构造函数。返回该Class对象的一个实例
        String getName() :返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称
        Class getSuperClass():返回当前Class对象的父类的Class对象
        Class [] getInterfaces() :获取当前Class对象的接口
        ClassLoader getClassLoader() :返回该类的类载入器
        Constructor[] getConstructors():返回一个包括某些Constructor对象的数组
        Field[] getFields():返回Field对象的一个数组
        Method getMethod(String name,Class  …  paramTypes):返回一个Method对象,此对象的形參类型为paramType
    ③实例化Class类对象(四种方法)
    1)前提:若已知详细的类,通过类的class属性获取,该方法 最为安全可靠,程序性能最高
           实例:Class clazz = String.class;
    2)前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象
           实例:Class clazz = new String().getClass();
    3)前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName(类的全类名)获取。可能抛出ClassNotFoundException
           实例:Class clazz = Class.forName(“java.lang.String”);
    4)其它:通过类载入器去载入
           ClassLoader loader = this.getClass().getClassLoader();
           Class clazz4 = loader.loadClass(“java.lang.String”);
    ④了解:类的载入过程
    当程序主动使用某个类时,假设该类还未被载入到内存中,则系统会通过例如以下三个步骤来对该类进行初始化
      1)将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类载入器完毕
      2)将类的二进制数据合并到JRE中
      3)JVM负责对类进行初始化
    ⑤了解:ClassLoader类载入器
    类载入器是用来把类(class)装载进内存的。

    JVM 规范定义了两种类型的类载入器:
    启动类载入器(bootstrap)和用户自己定义载入器(user-defined class loader)。
    JVM在执行时会产生3个类载入器组成的初始化载入器层次结构
      1)引导类载入器:用C++编写的,是JVM自带的类载入器,负责Java平台核心库,用来载入核心类库。该载入器无法直接获取
      2)扩展类载入器:负责jre/lib/ext文件夹下的jar包或 –D java.ext.dirs 指定文件夹下的jar包装入工作库
      3)系统类载入器:负责java –classpath 或 –D java.class.path所指的文件夹下的类与jar包装入工作 。是最经常使用的载入器
        //1.获取一个系统类载入器
        ClassLoader classloader = ClassLoader.getSystemClassLoader();
        System.out.println(classloader);
        //2.获取系统类载入器的父类载入器,即扩展类载入器
        classloader = classloader.getParent();
        //3.获取扩展类载入器的父类载入器。即引导类载入器
        classloader = classloader.getParent();
        //4.測试当前类由哪个类载入器进行载入
        classloader = Class.forName("exer2.ClassloaderDemo").getClassLoader();
        //5.測试JDK提供的Object类由哪个类载入器载入
        classloader = Class.forName("java.lang.Object").getClassLoader();
        //*6.关于类载入器的一个主要方法:getResourceAsStream(String str):获取类路径下的指定文件的输入流
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("exer2\test.properties");
    三、创建类对象并获取类的完整结构
    ①创建类的对象:调用Class对象的newInstance()方法
    要  求:1)类必须有一个无參数的构造器。
     2)类的构造器的訪问权限须要足够。
    若没有无參的构造器。仅仅能在操作的时候明白的调用类中的构造方法,并将參数传递进去之后,才干够实例化操作。

    过程例如以下:
            1)通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形參类型的构造器
            2)向构造器的形參中传递一个对象数组进去,里面包括了构造器中所需的各个參数。


            3)调用Constructor类的newInstance(object ... args)
    ②通过反射调用类的完整结构
    ②①获取相应的执行时类的属性 java.lang.reflect.Field
         1)Field[] getFields():仅仅能获取到执行时类中及其父类中声明为public的属性
         2)Field[] getDeclaredFields():获取执行时类本身声明的全部的属性
         3)Field getField(String fieldName):获取执行时类中声明为public的指定属性名为fieldName的属性
         4)Field getDeclaredField(String fieldName):获取执行时类中指定的名为fieldName的属性,能够获取全部的属性,包含private属性
         5)获取属性的各个部分的内容(权限修饰符  变量类型 变量名)
              1.获取每一个属性的权限修饰符
           int i = feild.getModifiers();返回代表修饰符的一个整数
           String str1 = Modifier.toString(i);通过Modifier的toString()将数值转化为字符串
       2.获取属性的类型
           Class type = feild.getType();:返回属性类型的Class对象
       3.获取属性名
           String str = feild.getName();返回属性的名称
         6)改动属性值方法一 (public String name;)
                    Class clazz = Person.class;
             //1.获取指定的属性getField(String fieldName):获取执行时类中声明为public的指定属性名为fieldName的属性
      Field name = clazz.getField("name");
      //2.创建执行时类的对象
      Person p = (Person)clazz.newInstance();
      System.out.println(p);
      //3.将执行时类的指定的属性赋值
      name.set(p,"Jerry");
         7)改动属性值方法二 (private int age;)
              //getDeclaredField(String fieldName):获取执行时类中指定的名为fieldName的属性
      Field age = clazz.getDeclaredField("age");
       //因为属性权限修饰符的限制。为了保证能够给属性赋值,须要在操作前使得此属性可被操作。


      age.setAccessible(true);
      age.set(p,10);
    ②②获取执行时类的方法 java.lang.reflect.Method
         1)Method[] getMethods():获取执行时类及其父类中全部的声明为public的方法
         2)Method[] getDeclaredMethods():获取执行时类本身声明的全部的方法
         3)Method getMethod(String methodName,Class ... params):获取执行时类中声明为public的指定的方法
         4)Method getDeclaredMethod(String methodName,Class ... params):获取执行时类中声明了的指定的方法
         5)获取方法的各个部分的内容(注解 权限修饰符 返回值类型 方法名 形參列表 异常)
             //1.注解
      Annotation[] ann = method.getAnnotations();
      //2.权限修饰符
      String str = Modifier.toString(method.getModifiers());
      //3.返回值类型
      Class returnType = method.getReturnType();
      //4.方法名
      String str = method.getName();
      //5.形參列表
      Class[] params = method.getParameterTypes();
      //6.异常类型
      Class[] exps = method.getExceptionTypes();
         6)调用执行时类中指定的方法一 [public void show()]
                    Class clazz = Person.class;
      //getMethod(String methodName,Class ... params):获取执行时类中声明为public的指定的方法
      Method method = clazz.getMethod("show");
      Person p = (Person)clazz.newInstance();
      //调用指定的方法:Object invoke(Object obj,Object ... obj)
      Object returnVal = m1.invoke(p);  :返回调用方法的返回值
      System.out.println(returnVal);

      //对于执行时类中静态方法的调用[public static void info()]
      Method method = clazz.getMethod("info");
      method.invoke(Person.class);
         7)调用执行时类中指定的方法二 [private int show(String nation,int age)] 
             //getDeclaredMethod(String methodName,Class ... params):获取执行时类中声明了的指定的方法
      Method method = clazz.getDeclaredMethod("display",String.class,int.class);
      //因为属性权限修饰符的限制,为了保证能够给属性赋值,须要在操作前使得此属性可被操作。 
      method.setAccessible(true);
      Object value = method.invoke(p,"CHN",10);
      System.out.println(value);
    ②③获取执行时类的构造器 java.lang.reflect.Constructor
          1)public Constructor<T>[] getConstructors()返回此 Class 对象所表示的类的全部public构造方法。


          2)public Constructor<T>[] getDeclaredConstructors()返回此 Class 对象表示的类声明的全部构造方法
          3)public Constructor<T> getConstructor(Class<?

    >... parameterTypes) :返回指定的public的构造器
          4)public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回类中声明了的指定的构造器。包含private构造器
          5)调用执行时类中指定的构造器一
                    String className = "com.lang.String";
      Class clazz = Class.forName(className);
       //创建相应的执行时类的对象。使用newInstance()。实际上就是调用了执行时类的空參的构造器。
      //要想可以创建成功:①要求相应的执行时类要有空參的构造器。

    ②构造器的权限修饰符的权限要足够。
      Object obj = clazz.newInstance();
      String p = (String)obj;
          6)调用执行时类中指定的构造器二
                    String1 className = "com.lang.String1";
      Class clazz = Class.forName(className);

                    Constructor cons = clazz.getConstructor(String.class,int.class);
                    String1 p = (String1)cons.newInstance("小三",20);
      
      Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
      cons.setAccessible(true);
      String1 p = (String1)cons.newInstance("小三",20);
    ②④获取执行时类的注解
      Class clazz = String.class;
      Annotation[] anns = clazz.getAnnotations();
      for(Annotation a : anns){
       System.out.println(a);
      }
    ②⑤获取执行时类所在的包
      Class clazz = String.class;
      Package pack = clazz.getPackage();
      System.out.println(pack);
     
    ②⑥获取执行时类的实现的接口
      Class clazz = Person.class;
      Class[] interfaces = clazz.getInterfaces();
      for(Class i : interfaces){
       System.out.println(i);
      }
     
    ②⑦*.获取执行时类的父类的泛型
      Class clazz = Person.class;
      Type type1 = clazz.getGenericSuperclass();
      
      ParameterizedType param = (ParameterizedType)type1;
      Type[] ars = param.getActualTypeArguments();
      
      System.out.println(((Class)ars[0]).getName());
    ②⑧获取带泛型的父类
      Class clazz = Person.class;
      Type type1 = clazz.getGenericSuperclass();
      System.out.println(type1);
     
    ②⑨获取执行时类的父类
      Class clazz = Person.class;
      Class superClass = clazz.getSuperclass();
      System.out.println(superClass);

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    增加新分类daily——“每天学了啥?”
    gcc选项中的编译过程
    一个带路径复制的perl脚本
    git
    mysql explain 详解
    CentOS Python2.4升级到Python2.7
    mongoDb查询
    linux php 扩展
    php-redis 扩展安装
    redis Linux的安装方法
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4732629.html
Copyright © 2011-2022 走看看