• Java进阶——反射


    引入

    动态编程语言

    变量并不是在计算机内存中被写入的某个值,它们只是指向内存的“标签”和“名称”,所以动态编程语言的变量没有一个固定的类型。Python

    静态编程语言

    静态编程语言的变量有固定的类型,它们指的是内存中的值。Java、C、C++

    介绍

    反射机制

    动态获取信息以及动态调用对象方法的功能。

    提供的功能

    • 运行时,判断任意一个对象所属类
    • 运行时,构造任意一个类的对象
    • 运行时,判断任意一个类所具有的成员方法和变量
    • 运行时,调用任意一个对象的方法
    • 生成动态代理

    反射机制原理

    RTTI 运行时类型信息

    运行期间,Java通过Class对象记录每个对象RTTI,当编写并编译一个新类时,就会产生一个Class对象。

    Class对象是在加载类时由JVM构造的,JVM为每个类管理一个独一无二的Class对象。

    动态的生成字节码(.class文件),加载到JVM中运行。

    使用的类

    Class类

    Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
    实例表示正在运行的Java应用程序中的类和接口。
    获取Class对象:

    • Object.getClass();
    • Class.getSuperClass();
    • Class.forName();
    • 对于包装器类型:类名.TYPE属性。

    Field类

    提供有关类和接口的属性信息,以及对其动态访问权限。

    Constructor类

    提供类的单个构造方法信息,以及对其的访问权限。

    Method类

    提供类和接口单独的某个方法的信息。

    功能使用

    获取对象的类

    • getClass()
      //1.1 getClass()
      //获取对象的类
      String str = "hello world!";
      cls = str.getClass();
      System.out.println(cls.getName());
      
    • Class.forName()
      • 类加载器加载方法
      //1.2  Class.forName();
      //根据具体包名来获取类
      //字符串合法命名是类的命名空间和类的名称组成
      cls = Class.forName("reflectprj.Student");
      

    获取类的父类

    • Class对象且该对象有父类
      //1.3 getSuperclass();
      //获取类的父类
      Class superCls = cls.getSuperclass();
      

    获取类的构造方法

    • 获取全部的构造方法getDeclaredConstructors()
    • 获取特定的构造方法getDeclaredConstructor(Class[] class)
    • 创建构造方法创建实例newInstance(参数)
      //3.1 getDeclaredConstructors();
      //获取类的构造方法
      Constructor[] constructors;
      constructors = cls.getDeclaredConstructors();
      for(Constructor constructor:constructors) {
            System.out.println(constructor.toString());
      }
      //3.1.2 
      //获取类特定的构造方法
        
      Class[] var = {int.class,String.class,String.class};
      Constructor constructor = cls.getDeclaredConstructor(var);
      System.out.println(constructor.toString());
        		
      //4.1 newInstance();
      //通过构造方法创建实例
      Student stu = (Student)constructor.newInstance(1,"王小明","man");
      System.out.println(stu.toString());
      

    获取类的方法

    • 获取全部的方法getDeclaredMethods()
    • 获取特定的方法getDeclaredMethod("方法名",Class[])
    • 将对象与方法关联,并调用方法。invoke(对象名,参数)
    • 如果方法为私有,则调用method.setAccessible(true)
      //3.2 getDeclaredMethod();
      //获取类的方法
      Method [] ms = cls.getDeclaredMethods();
      for(Method m:ms) {
          System.out.println(m.getName());
      }
      
      //4.2 invoke();
      //调用类的方法
      Method m = cls.getDeclaredMethod("setSex", String.class);
      m.invoke(stu, "women");
      System.out.println(stu.toString());
      
      //5 setAccessible()
      //调用私有方法
      m = cls.getDeclaredMethod("print", null);
      m.setAccessible(true);
      m.invoke(stu,null);
      

    获取类的属性

    • 获取全部的属性getDeclaredFields()
    • 获取特定的属性getDeclaredField("fieldName")
    • 将对象与属性关联,并设置属性set(对象名,属性)
    • 将对象与属性关联,获取属性get(对象名)
    • 如果属性为私有,则调用method.setAccessible(true)
      //3.3 getDeclaredField()
      //获取类的属性
      Field fs[] = cls.getDeclaredFields();
      for(Field f:fs) {
            System.out.println(f.getName());
      }
      
      //4.3 set();
      //设置私有类属性
      Field f = cls.getDeclaredField("sex");
      f.setAccessible(true);
      f.set(stu,"men");
      System.out.println(f.get(stu).toString());
      

    反射的应用

    操作数据库

    动态创建SQL语句。

    public void save(Object obj) {
          String sql = "insert into ";
          try {
                Class cls = obj.getClass();
                String clsName = cls.getSimpleName();
                sql+=clsName;
                sql+="(";
                Field fs[] = cls.getDeclaredFields();
                for(Field f:fs) {
                      sql+=f.getName()+",";
                }
                sql = sql.substring(0, sql.length()-1);
                sql+=") values(";
                Field fs1[] = cls.getDeclaredFields();
                for(Field f:fs1) {
                      f.setAccessible(true);
                      sql+=f.get(obj)+",";
                }
                sql = sql.substring(0, sql.length()-1);
                sql+=")";
          }catch(Exception e) {
                e.printStackTrace();
          }
          System.out.println(sql);
    }
    

    解析XML

    解析XML动态生成对象。(Spring框架)

    动态代理

    动态代理

    框架使用

    • Spring框架
    • Hibernate框架
    • Struts框架

    缺点

    反射对于性能有影响,反射基本上是一种解释操作。
    可以告诉JVM希望做什么,让其满足要求。
    这类操作慢于直接执行相同的操作。

  • 相关阅读:
    背水一战 Windows 10 (61)
    背水一战 Windows 10 (60)
    背水一战 Windows 10 (59)
    背水一战 Windows 10 (58)
    背水一战 Windows 10 (57)
    背水一战 Windows 10 (56)
    背水一战 Windows 10 (55)
    背水一战 Windows 10 (54)
    背水一战 Windows 10 (53)
    背水一战 Windows 10 (52)
  • 原文地址:https://www.cnblogs.com/occlive/p/reflect.html
Copyright © 2020-2023  润新知