反射

作者: lisx_ | 来源:发表于2020-04-09 15:58 被阅读0次

    通过 Class 对象分别获取Constructor类对象、Method类对象 & Field 类对象

    // 即以下方法都属于`Class` 类的方法。
    
    <-- 1. 获取类的构造函数(传入构造函数的参数类型)->>
      // a. 获取指定的构造函数 (公共 / 继承)
      Constructor<T> getConstructor(Class<?>... parameterTypes)
      // b. 获取所有的构造函数(公共 / 继承) 
      Constructor<?>[] getConstructors(); 
      // c. 获取指定的构造函数 ( 不包括继承)
      Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
      // d. 获取所有的构造函数( 不包括继承)
      Constructor<?>[] getDeclaredConstructors(); 
    // 最终都是获得一个Constructor类对象
    
    // 特别注意:
      // 1. 不带 "Declared"的方法支持取出包括继承、公有(Public) & 不包括有(Private)的构造函数
      // 2. 带 "Declared"的方法是支持取出包括公共(Public)、保护(Protected)、默认(包)访问和私有(Private)的构造方法,但不包括继承的构造函数
      // 下面同理
    
    <--  2. 获取类的属性(传入属性名) -->
      // a. 获取指定的属性(公共 / 继承)
       Field getField(String name) ;
      // b. 获取所有的属性(公共 / 继承)
       Field[] getFields() ;
      // c. 获取指定的所有属性 (不包括继承)
       Field getDeclaredField(String name) ;
      // d. 获取所有的所有属性 (不包括继承)
       Field[] getDeclaredFields() ;
    // 最终都是获得一个Field类对象
    
    <-- 3. 获取类的方法(传入方法名 & 参数类型)-->
      // a. 获取指定的方法(公共 / 继承)
        Method getMethod(String name, Class<?>... parameterTypes) ;
      // b. 获取所有的方法(公共 / 继承)
       Method[] getMethods() ;
      // c. 获取指定的方法 ( 不包括继承)
       Method getDeclaredMethod(String name, Class<?>... parameterTypes) ;
      // d. 获取所有的方法( 不包括继承)
       Method[] getDeclaredMethods() ;
    // 最终都是获得一个Method类对象
    
    <-- 4. Class类的其他常用方法 -->
    getSuperclass(); 
    // 返回父类
    
    String getName(); 
    // 作用:返回完整的类名(含包名,如java.lang.String ) 
     
    Object newInstance(); 
    // 作用:快速地创建一个类的实例
    // 具体过程:调用默认构造器(若该类无默认构造器,则抛出异常 
    // 注:若需要为构造器提供参数需使用java.lang.reflect.Constructor中的newInstance()
    

    通过 Constructor类对象、Method类对象 & Field类对象分别获取类的构造函数、方法 & 属性的具体信息 & 进行操作

    // 即以下方法都分别属于`Constructor`类、`Method`类 & `Field`类的方法。
    
    <-- 1. 通过Constructor 类对象获取类构造函数信息 -->
      String getName();// 获取构造器名
      Class getDeclaringClass();// 获取一个用于描述类中定义的构造器的Class对象
      int getModifiers();// 返回整型数值,用不同的位开关描述访问修饰符的使用状况
      Class[] getExceptionTypes();// 获取描述方法抛出的异常类型的Class对象数组
      Class[] getParameterTypes();// 获取一个用于描述参数类型的Class对象数组
    
    <-- 2. 通过Field类对象获取类属性信息 -->
      String getName();// 返回属性的名称
      Class getDeclaringClass(); // 获取属性类型的Class类型对象
      Class getType();// 获取属性类型的Class类型对象
      int getModifiers(); // 返回整型数值,用不同的位开关描述访问修饰符的使用状况
      Object get(Object obj) ;// 返回指定对象上 此属性的值
      void set(Object obj, Object value) // 设置 指定对象上此属性的值为value
     
    <-- 3. 通过Method 类对象获取类方法信息 -->
      String getName();// 获取方法名
      Class getDeclaringClass();// 获取方法的Class对象 
      int getModifiers();// 返回整型数值,用不同的位开关描述访问修饰符的使用状况
      Class[] getExceptionTypes();// 获取用于描述方法抛出的异常类型的Class对象数组
      Class[] getParameterTypes();// 获取一个用于描述参数类型的Class对象数组
    
    <--额外:java.lang.reflect.Modifier类 -->
    // 作用:获取访问修饰符
    
    static String toString(int modifiers)   
    // 获取对应modifiers位设置的修饰符的字符串表示
    
    static boolean isXXX(int modifiers) 
    // 检测方法名中对应的修饰符在modifiers中的值
    
    package com.example.myapplication;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Ltest {
    
        public static abstract class Product {
            public abstract void show();
        }
    
        public static class ProductA extends Product {
    
            @Override
            public void show() {
                System.out.println("生产出了产品A");
            }
        }
    
        class ProductB extends Product {
    
            @Override
            public void show() {
                System.out.println("生产出了产品B");
            }
        }
    
        public static void main(String[] args) {
    
            //test();
            //test1();
            test2();
        }
    
    
        /**
         * 测试反射_内部类
         */
        private static void test2() {
            // 静态内部类可直接 class.newInstance
            try {
                // 1. 根据 传入的产品类名 获取 产品类类型的Class对象
                Class product_Class = Class.forName(
                        "com.example.myapplication.Ltest$ProductA");
                // 2. 通过Class对象动态创建该产品类的实例
                Product concreteProduct = (Product) product_Class.newInstance();
                concreteProduct .show();
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
    
            // 成员内部类需要先构造外部类
            try {
                Class outClass = Class.forName(
                        "com.example.myapplication.Ltest");
    
                Class innerClass = Class.forName(
                        "com.example.myapplication.Ltest$ProductB");
                // 获取非静态内部类的实例,需要先获取外部类实例
                Product b = (Product) innerClass.getDeclaredConstructors()[0].newInstance(
                        outClass.newInstance());
                b.show();
                // 另一种方式_创建实例
                Product b2 = (Product) innerClass.getDeclaredConstructor(outClass).newInstance(
                        outClass.newInstance());
                b2.show();
                // 另一种方式_调用方法
                Method method = innerClass.getDeclaredMethod("show");
                method.invoke(b);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
        /**
         * 测试反射_基本用法
         */
        private static void test1() {
    
            class Student {
    
                private String name;
    
                // 无参构造函数
                public Student() {
                    System.out.println("调用了无参构造函数");
                }
    
                // 有参构造函数
                public Student(String str) {
                    System.out.println("调用了有参构造函数");
                }
    
                // 无参数方法
                public void setName1() {
                    System.out.println("调用了无参方法:setName1()");
                }
    
                // 有参数方法
                public void setName2(String str) {
                    System.out.println("调用了有参方法setName2 str:" + str);
                }
            }
    
            try {
    
                // 1. 获取Student类的Class对象
                Class studentClass = Student.class;
    
                // 3. 通过Class对象获取Student类的name属性
                Field f = studentClass.getDeclaredField("name");
                // 4. 设置私有访问权限
                f.setAccessible(true);
                // 2. 通过Class对象创建Student类的对象
                Object mStudent = studentClass.newInstance();
                // 5. 对新创建的Student对象设置name值
                f.set(mStudent, "Carson_Ho");
                // 6. 获取新创建Student对象的的name属性 & 输出
                System.out.println(f.get(mStudent));
    
                //利用反射调用构造函数
    
                // 2.1 通过Class对象获取Constructor类对象,从而调用无参构造方法
                // 注:构造函数的调用实际上是在newInstance(),而不是在getConstructor()中调用
                Object mObj1 = studentClass.getConstructor().newInstance();
                // 2.2 通过Class对象获取Constructor类对象(传入参数类型),从而调用有参构造方法
                Object mObj2 = studentClass.getConstructor(String.class).newInstance("Carson");
    
    
                // 3.1 通过Class对象获取方法setName1()的Method对象:需传入方法名
                // 因为该方法 = 无参,所以不需要传入参数
                Method msetName1 = studentClass.getMethod("setName1");
                // 通过Method对象调用setName1():需传入创建的实例
                msetName1.invoke(mStudent);
                // 3.2 通过Class对象获取方法setName2()的Method对象:需传入方法名 & 参数类型
                Method msetName2 = studentClass.getMethod("setName2", String.class);
                // 通过Method对象调用setName2():需传入创建的实例 & 参数值
                msetName2.invoke(mStudent, "Carson_Ho");
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
    
        /**
         * 测试class_name
         */
        private static void test() {
            // 对于2个String类型对象,它们的Class对象相同
            Class<?> c1, c2, c3, c4;
            c1 = "Carson".getClass();
            c2 = null;
            try {
                c2 = Class.forName("java.lang.String");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            c3 = String.class;
            c4 = Boolean.TYPE;
            System.out.println("1=" + c1);
            System.out.println("2=" + c2);
            System.out.println("3=" + c3);
            System.out.println("4=" + c4);
        }
    }
    
    

    相关文章

      网友评论

          本文标题:反射

          本文链接:https://www.haomeiwen.com/subject/cnrqaqtx.html