文章目录
  1. 1. Class类的使用
  2. 2. Java动态加载类
  3. 3. Java获取方法信息
  4. 4. 获取成员变量与构造函数的信息
  5. 5. Java方法反射的基本操作
  6. 6. 最后的最后

Class类的使用

  • 传送万物皆对象,那么类是谁的对象呢?
    • 时java.lang.Class这个类的!没想到吧!
    • 所以说任何一个类都是Class类的实例对象
  • 这个实例对象有三种表达方式 :

    • 就不多说了直接上代码好啦

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      //首先假装我们已经有一个Demo类了,实例化它
      Demo demo = new Demo();
      //然后我们能怎么得到这个类呢?
      //第一种方式 :直接由 类名.class 得到
      Class c1 = Demo.class;
      //第二种方式 :已知该类的对象,通过 对象.getClass() 得到
      Class c2 = demo.getClass();
      //第三种方式 :直接通过 Class.forName() 得到
      Class c3 = null;
      try {
      c3 = Class.forName("com.demo.reflect.Demo");
      } catch (ClassNotFoundException e) {
      e.printStackTrack();
      }
    • 还有一点要注意的就是

      • c1、c2、c3 被称为类的类类型
      • 且 c1 是 == c2 == c3 的
  • 通过类的类类型直接创建该类的实例对象

    • 比如像这样 :

      1
      2
      3
      4
      5
      6
      7
      //注意要做一个强制类型转换,还有要处理一下异常
      try {
      Demo demoFromC1 = (Demo)c1.newInstance();
      demoFromC1.print();
      } catch (Exception e) {
      e.printStackTrack();
      }
    • 注意能直接创建的的前提是这个类要有无参构造方法

Java动态加载类

  • 静态加载类 :
    • 即在编译时刻就要加载所有可能用到的类
    • 也就是说一个类不存在 整个就编译不通过
    • 比如说用new创建对象的话 就属于静态加载
  • 动态加载类 :

    • 即在使用时才去加载这个要用到的类
    • 也就是说就算这个类不存在
    • 只要还没开始使用它 就是可以通过编译的
    • 就比如说 这样 :

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      public static void main(String[] args){
      try {
      //动态加载类,在运行时加载
      Class c = Class.forName(args[0]);
      //将这个类转换为交通工具类
      Vehicle vehicle = (vehicle)c.newInstance();
      //假装有一个run()方法
      Vehicle.run();
      } catch (Exception e) {
      e.printStackTrack();
      }
      }
    • 然后其他类就可以通过实现 Vehicle 这个接口来直接被调用啦,完全不用改动main方法里的代码

Java获取方法信息

  • “编写一个获取类信息的方法” :

    • 抄写一个获取方法信息的方法 :

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      public void printClassMessage(Object obj) {
      //首先获取类类型
      Class c = obj.getClass();
      //获取类的名称
      System.out.println("类的名称为 :" + c.getName());

      //getMethods():取得所有public函数
      //包括继承父类而来的
      Method[] methods = c.getMethods();
      //getDeclaredMethods():获取所有该类自己声明的方法
      //不论访问权限,不包括父类函数
      //c.getDeclaredMethods();

      for(int i = 0; i < methods.length; i++) {
      //得到方法的返回值类型的类类型
      Class returnType = methods.getReturnType();
      //打印方法的返回类型
      System.out.print(returnType.getName + " ");
      //得到方法的名称
      System.out.print(methods[i].getName() + "(" );
      //获取参数类型(得到的是参数列表的类型的类类型)
      Class[] paramTypes = methods[i].getParameterType();
      for(Class class : paramTypes) {
      //其实这个逗号有点bug但是算了
      System.out.print(class.getName() + ",");
      }
      System.out.println( ")" );
      }
      }
    • 然后要怎么调用呢?这样子 :

      1
      2
      3
      String s = "hello";
      printClassMessage(s);
      然后就会打印出String的类信息啦

获取成员变量与构造函数的信息

  • 继续编写一个获取类信息的方法 :

    • 抄写一个获取成员变量的方法 :

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      //getFields()方法获取的是所有public的成员变量信息
      //Filed[] fields = c.getFileds();
      //getDeclaredFields()获取的是该类自己声明的成员变量
      Field[] fidlds = c.getDeclaredFields();
      for(Field field : fields) {
      Class fieldType = field.getType();
      //得到成员变量的类类型
      String typeName = fieldType.getName();
      //得到成员变量的名称
      String filedName = field.getName();
      System.out.println(typeName + " " + fieldName);
      }
    • 抄写一个获取构造函数信息的方法 :

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      Class c = obj.getClass();
      //getConstructors() :获取所有public的构造函数
      //Constructor[] cs = c.getConstructors();
      //getDeclaredConstructors :获取所有自己定义的构造函数
      Constructor[] cs = c.getDeclaredConstructors();
      for(Constructor constructor : cs) {
      //获取构造函数的参数列表(得到参数列表的类类型)
      System.out.print(constructor.getParameterTypes());
      for(Class class : paramTypes) {
      //同样,这里的逗号也有点bug啦
      System.out.print(class.getName() + ",");
      }
      System.out.println( ")" );
      }
    • 所以说其实只要得到了这个类的类类型,一切都好说;只需要要c.一下,什么都出来了啦

Java方法反射的基本操作

简单一点来说就是用方法对象来调用方法

  • 不用反射的话是这样的 :

    • (假设有一个Demo类,里面有一个tell()方法)
      1
      2
      Demo demo = new Demo();
      demo.tell();
  • 用反射的话是这样的 :

    • (假设tell的参数列表为为 String, int)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      Class c = demo.getClass();
      try {
      //首先获取到这个方法
      Method method = c.getMethod("tell",String.class,int.class);
      //然后进行方法的反射操作
      //即使用method这个对象来调用方法
      method.invoke("你好",2018);
      } catch (Exception e) {
      e.printStackTrack();
      }

最后的最后

  • 为什么要使用反射呢?
    • 个人感觉最大的优势可能还是在于易扩展吧
    • 就比如说你写的那个Excel导入导出
    • 总有一种加上反射就可以随传随导的感觉啊!!!
    • 求你了赶紧好好学习一下反射看看能不能改一下好嘛!
    • 现有代码的入侵太多了啦 !!!
文章目录
  1. 1. Class类的使用
  2. 2. Java动态加载类
  3. 3. Java获取方法信息
  4. 4. 获取成员变量与构造函数的信息
  5. 5. Java方法反射的基本操作
  6. 6. 最后的最后