反射机制入门

这是关于反射机制的一篇笔记。 视频教程地址

  • 概念:将类的各个组成部分封装为其他对象,就是反射机制

  • 好处:

    • 可以在程序运行中操作这些对象
    • 可以解耦,提高程序的可扩展性。
  • 获取class对象的方式:

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

      • 多用于配置文件,将类名定义在配置文件中,读取文件,加载类。
    2. 类名.class 通过类名的属性class获取

      • 多用于参数的传递
    3. 对象.getClass()getClass()方法在Object类中定义着。

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

    5. 代码

      //1.Class.forName("全类名");
      Class cls1 = Class.forName("com.qmh.domain.Person");
      System.out.println(cls1);
      //2.类名.class
      Class cls2 = Person.class;
      System.out.println(cls2);
      //3.对象.getClass()
      Person p = new Person();
      Class cls3 = p.getClass();
      System.out.println(cls3);
      
  • Class对象功能:

    • 获取成员变量们

      • public Field[] getFields() :获取所有public修饰的成员变量
      • public Field getField(String name)::获取指定名称的public修饰的成员变量
      • public Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
      • public Field getDeclaredField(String name):获取指定名称的成员变量,不考虑修饰符
    • 获取构造方法们

      • public Constructor<?>[] getConstructors()
      • public Constructor<T> getConstructor(类<?>... parameterTypes)
      • public Constructor<?>[] getDeclaredConstructors()
      • public Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
    • 获取成员方法们

      • public Method[] getMethods()
      • public Method getMethod(String name,类<?>... parameterTypes)
      • public Method[] getDeclaredMethods()
      • public Method getDeclaredMethod(String name,类<?>... parameterTypes)
    • 获取类名

      • String getName()
      //获取类名
      String className = personClass.getName();
      System.out.println(className);
      
  • Field:成员变量

    • 操作:

      • 获取值 public Object get(Object obj)
      • 设置值 public void set(Object obj,Object value)
      • 忽略访问权限修饰符的安全检查 name.setAccessible(true); //暴力反射
    • 代码:

      //1.获取Person的Class对象
              Class<Person> personClass = Person.class;
              //2.获取成员变量们
              Field[] fields = personClass.getFields();
              for(Field field:fields){
                  System.out.println(field);
              }
              System.out.println("--------------");
              //3.获取指定名称的成员变量
              Field a = personClass.getField("a");
              //获取a的值
              Person p = new Person();
              Object o = a.get(p);
              System.out.println(o);
              //设置a的值
              a.set(p,"张三");
              System.out.println(p);
              System.out.println("--------------");
              //获取所有的成员变量,不考虑修饰符
              Field[] declaredFields = personClass.getDeclaredFields();
              for(Field declaredField : declaredFields){
                  System.out.println(declaredField);
              }
              // 访问某个私有成员变量,
              Field name = personClass.getDeclaredField("name");
              //忽略访问权限符的安全检查
              name.setAccessible(true); //暴力反射
              Object o1 = name.get(p);
              System.out.println(o1);
              name.set(p,"李四");
              System.out.println(p);
      
  • Constructor:构造方法

    • 创建对象 public T newInstance(Object... initargs)
    • 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance()方法
    • 代码:
    //1.获取Person的Class对象
    Class<Person> personClass = Person.class;
    //获取某个构造方法
    Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
    System.out.println(constructor);
    //创建对象
    Person person = constructor.newInstance("张三", 18);
    System.out.println(person);
    System.out.println("--------------");
    //空参构造方法
    Person person2 = personClass.newInstance();
    System.out.println(person2);
    
  • Method 方法对象

    • 执行方法 public Object invoke(Object obj,Object... args)
    • 获取方法名称:method.getName()
    • 代码:
    		//1.获取Person的Class对象
            Class<Person> personClass = Person.class;
            // 获取空参方法
            Method eat = personClass.getMethod("eat");
            Person p = new Person();
            //执行方法
            eat.invoke(p);
            //获取带参方法 参数:方法名和参数类
            Method eat1 = personClass.getMethod("eat", String.class);
            //执行方法,传入对象和参数
            eat1.invoke(p, "饭");
            //获取所有public修饰的方法
            Method[] methods = personClass.getMethods();
            for(Method method:methods){
                System.out.println(method);
                String name = method.getName();
                System.out.println(name);
            }
    
  • 案例:

    • 需求:写一个“框架”,不能改变该类的任何代码,可以帮助我们创建任意类的对象,并执行其中任意类的方法

    • 实现:

      1. 配置文件
      2. 反射
    • 步骤

      1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
      2. 在程序中加载配置文件
      3. 使用反射技术来加载类文件进内存
      4. 创建对象
      5. 执行方法
    • 配置文件内容:

      className = com.qmh.domain.Student
      methodName = sleep
      
    • 测试代码:

      public static void main(String[] args) throws Exception {
          //不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法
          /*Person p = new Person();
          p.eat();*/
          //1.加载配置文件
          //1.1 创建Properties对象
          Properties pro = new Properties();
          //1.2加载配置文件,转换为一个集合
          pro.load(Resources.getResourceAsStream("pro.properties"));
          //2.获取配置文件中定义的数据
          String className = pro.getProperty("className");
          String methodName = pro.getProperty("methodName");
          //3.加载该类进内存
          Class cls = Class.forName(className);
          //4.创建对象 无参构造函数
          Object o = cls.newInstance();
          //5.获取方法对象
          Method method = cls.getMethod(methodName);
          //6.执行方法
          method.invoke(o);
      }
      
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章