zoukankan      html  css  js  c++  java
  • 反射

    反射:框架设计的灵魂

    名词解释:
        * 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
        * 反射:将类的各个组成部分封装为其他对象,这就是反射机制        
    使用反射优点:
            1. 可以在程序运行过程中,操作这些对象。
            2. 可以解耦,提高程序的可扩展性。

    获取Class对象的方式

    1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
          * 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
    2. 类名.class:通过类名的属性class获取
          * 多用于参数的传递
    3. 对象.getClass():getClass()方法在Object类中定义着。
          * 多用于对象的获取字节码的方式

    三种方式获取Class对象代码

     1 package demo14.reflect;
     2 
     3 public class demo01 {
     4     public static void main(String[] args) throws ClassNotFoundException {
     5         // 1 Class.forName("全类名")
     6         Class aClass = Class.forName("demo14.reflect.Person");
     7         System.out.println(aClass);
     8 
     9         // 2 类名.class
    10         Class bClass = Person.class;
    11         System.out.println(bClass);
    12 
    13         // 3 对象.getClass()
    14         Person person = new Person();
    15         Class cClass = person.getClass();
    16         System.out.println(cClass);
    17 
    18         //检查三种方式获取的Class对象是否一致
    19         System.out.println(aClass == bClass);
    20         System.out.println(bClass == cClass);
    21         
    22     }
    23 }

    执行结果

    # 注:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

     Class对象功能

    1. 获取成员变量们
         * Field[] getFields() :获取所有public修饰的成员变量
         * Field getField(String name)   获取指定名称的 public修饰的成员变量
    
         * Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
         * Field getDeclaredField(String name)  
    2. 获取构造方法们
         * Constructor<?>[] getConstructors()  
         * Constructor<T> getConstructor(类<?>... parameterTypes)  
    
         * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)  
         * Constructor<?>[] getDeclaredConstructors()  
    3. 获取成员方法们:
         * Method[] getMethods()  
         * Method getMethod(String name, 类<?>... parameterTypes)  
    
         * Method[] getDeclaredMethods()  
         * Method getDeclaredMethod(String name, 类<?>... parameterTypes)  
    
    4. 获取全类名    
         * String getName()  
    Field:成员变量
        * 操作:
           1. 设置值
              * void set(Object obj, Object value)  
           2. 获取值
              * get(Object obj) 
           3. 忽略访问权限修饰符的安全检查
              * setAccessible(true):暴力反射
    
    Constructor:构造方法
        * 创建对象:
            * T newInstance(Object... initargs)  
            * 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
    
    Method:方法对象
         * 执行方法:
            * Object invoke(Object obj, Object... args)  
         * 获取方法名称:
            * String getName:获取方法名

    Class对象获取成员变量、对成员变量值进行获取与设置代码示例

     1 package demo14.reflect;
     2 
     3 import java.lang.reflect.Field;
     4 
     5 public class demo02 {
     6     public static void main(String[] args) throws Exception {
     7         /*
     8          * Field[] getFields() :获取所有public修饰的成员变量
     9          * Field getField(String name)   获取指定名称的 public修饰的成员变量
    10 
    11          * Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
    12          * Field getDeclaredField(String name)  获取指定名称的成员变量 不考虑修饰符
    13          */
    14 
    15         // 1 获取Class对象
    16         Class cls = Class.forName("demo14.reflect.Person");
    17 
    18         // 2 获取成员变量方法
    19         // 2.1 获取所有的public修饰的成员变量
    20         Field[] fields = cls.getFields();
    21         for (Field field : fields) {
    22             System.out.println(field);
    23         }
    24         // 2.2 获取指定的public修饰的成员变量
    25         Field a = cls.getField("a");
    26         System.out.println(a);
    27         //2.2.1获取和设置Field值
    28         Person person = new Person();
    29         Object o = a.get(person);
    30         System.out.println(o);
    31         a.set(person, "kelvin");
    32         System.out.println(person);
    33 
    34         // 2.3 获取所有的成员变量
    35         Field[] declaredFields = cls.getDeclaredFields();
    36         for (Field field : declaredFields) {
    37             System.out.println(field);
    38         }
    39 
    40         // 2.4 获取指定的成员变量
    41         Field d = cls.getDeclaredField("d");
    42         System.out.println(d);
    43         //忽略访问权限修饰符的安全检查(暴力反射)
    44         d.setAccessible(true);
    45         //2.4.1获取和设置非public修饰的Field值
    46         Person person1=new Person();
    47         Object o1 = d.get(person1);
    48         System.out.println(o1);
    49         d.set(person1,"jack");
    50         System.out.println(person1);
    51     }
    52 }

    Class对象获取构造方法,并根据构造方法创建对象

     1 package demo14.reflect;
     2 
     3 import java.lang.reflect.Constructor;
     4 import java.util.Arrays;
     5 
     6 public class demo03 {
     7     public static void main(String[] args) throws Exception {
     8         /*
     9          Constructor<?>[] getConstructors()
    10          Constructor<T> getConstructor(类<?>... parameterTypes)
    11 
    12          Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
    13          Constructor<?>[] getDeclaredConstructors()
    14 
    15         创建对象:
    16         T newInstance(Object... initargs)
    17         如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
    18 
    19          */
    20 
    21         Class cls = Class.forName("demo14.reflect.Person");
    22         // 1 获取所有public修饰的构造方法
    23         Constructor[] constructors = cls.getConstructors();
    24         System.out.println(Arrays.toString(constructors));
    25 
    26         // 2 获取指定的参数的构造方法
    27         Constructor constructor = cls.getConstructor(String.class, int.class);
    28         System.out.println(constructor);
    29         // 2.1 使用有参构造方法创建对象
    30         Object kelvin = constructor.newInstance("kelvin", 23);
    31         System.out.println(kelvin);
    32 
    33         // 3 获取无参构造方法
    34         Constructor constructor1 = cls.getConstructor();
    35         System.out.println(constructor1);
    36         // 3.1 使用无参构造方法创建对象
    37         // 方式一
    38         Object o = constructor1.newInstance();
    39         System.out.println(o);
    40         // 方式二
    41         Object o1 = cls.newInstance();
    42         System.out.println(o1);
    43 
    44 
    45     }
    46 }

    Class获取成员方法并执行

     1 package demo14.reflect;
     2 
     3 import java.lang.reflect.Method;
     4 import java.util.Arrays;
     5 
     6 public class demo04 {
     7     public static void main(String[] args) throws Exception {
     8         /*
     9           Method[] getMethods()
    10           Method getMethod(String name, 类<?>... parameterTypes)
    11 
    12           Method[] getDeclaredMethods()
    13           Method getDeclaredMethod(String name, 类<?>... parameterTypes)
    14 
    15           执行方法:
    16             Object invoke(Object obj, Object... args)
    17           获取方法名称:
    18             String getName:获取方法名
    19 
    20          */
    21         Class cls = Class.forName("demo14.reflect.Person");
    22 
    23         // 1 获取所有的public成员方法
    24         Method[] methods = cls.getMethods();
    25         System.out.println(Arrays.toString(methods));
    26         // 2 获取指定的public成员带参方法
    27         Person person = new Person();
    28         Method run = cls.getMethod("run", String.class);
    29         run.invoke(person, "kelvin");
    30         // 3 获取指定的public修饰无参成员方法
    31         Method run1 = cls.getMethod("run");
    32         run1.invoke(person);
    33 
    34         // 4 获取private修饰的成员方法
    35         Method eat = cls.getDeclaredMethod("eat");
    36         // 暴力反射
    37         eat.setAccessible(true);
    38         eat.invoke(person);
    39     }
    40 }

    反射应用实例

    借助配置文件,配置文件可以配置类和方法。

     1 package demo14.reflect;
     2 
     3 import java.io.IOException;
     4 import java.io.InputStream;
     5 import java.lang.reflect.Method;
     6 import java.util.Properties;
     7 
     8 public class demotest {
     9     /*
    10     不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法
    11     */
    12     public static void main(String[] args) throws Exception {
    13         Properties pro = new Properties();
    14 
    15         ClassLoader classLoader = demotest.class.getClassLoader();
    16         InputStream resourceAsStream = classLoader.getResourceAsStream("demo14/reflect/pro.properties");
    17         pro.load(resourceAsStream);
    18 
    19         String className = pro.getProperty("className");
    20         String classMethod = pro.getProperty("classMethod");
    21 
    22         Class cls = Class.forName(className);
    23         Method method = cls.getMethod(classMethod);
    24 
    25         Object o = cls.newInstance();
    26         method.invoke(o);
    27     }
    28 }

    配置文件

    className=demo14.reflect.Student
    classMethod=study

     反射图解

     

  • 相关阅读:
    POJ3624 01背包入门
    51Nod 1085 01背包
    linux配置安装tengine(centos6.5 )
    nginx列出目录
    Black and white painting
    Train Problem I
    快速排序的题
    数据结构实验之求二叉树后序遍历和层次遍历
    (转)最大子序列和问题 看着貌似不错
    数据结构实验之二叉树的建立与遍历
  • 原文地址:https://www.cnblogs.com/sun-10387834/p/13528770.html
Copyright © 2011-2022 走看看