美文网首页
Java核心技术(卷I) 11、反射

Java核心技术(卷I) 11、反射

作者: kaiker | 来源:发表于2021-03-06 19:33 被阅读0次

    能够分析类能力的程序称为反射

    1、反射机制的作用

    • 在运行时分析类的能力
    • 在运行时检查对象
    • 实现泛型数组操作代码
    • 利用Method对象

    2、Class类

    • Java运行时系统始终为所有对象维护一个运行时类标识,这个信息会跟踪每个对象所属的类。
    • 虚拟机利用运行时类型信息选择要执行的正确的方法
    • 可以使用Class类访问这些信息
    • Class类实际上是一个泛型类,Employee.class的类型是Class<Employee>
    Employee e;
    Class cl = e.getClass();  // 如果e是Employee则cl是Employee,如果e是Manager则cl是Manager
    
    • 如果有一个Class类型的对象,可以用它来构造类实例
    var className = "java.util.Random";
    Class cl = Class.forName(className);
    Object obj = cl.getConstructor().newInstance(); // 如果没有无参构造器会抛出异常
    

    3、利用反射分析类的能力

    • Field 类的描述字段 getFields
    • Method 类的方法 getMethods
    • Constructor 类的构造器 getConstructor
    var harry = new Employeee("Harry P",5000,10,1,1989);
    Class cl = harry.getClass(); // Employee
    Field f = cl.getDeclaredField("name"); // Employee的name这个字段
    Object v = f.get(harry); // 获取的是harry的name字段的值
    

    4、反射案例

    扩展一个Array数组

    • 目的是扩展一个已经填满的数组
    public static Object[] badCopyOf(Object[] a, int newLength) // not useful  因为Object没法转换成其他类型的数组
       {
          Object[] newArray = new Object[newLength];
          System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));
          return newArray;
       }
    
    • 为了实现一个通用的扩展数组的方法,可以用反射在运行的时候获取数组里元素的类型
    public static Object goodCopyOf(Object a, int newLength) 
       {
          Class cl = a.getClass();
          if (!cl.isArray()) return null;
          Class componentType = cl.getComponentType(); // 返回数组中元素的Class对象,如果不是Class对象那么返回null
          int length = Array.getLength(a);
          Object newArray = Array.newInstance(componentType, newLength);
          System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));
          return newArray;
       }
    
    
    • Array.newInstance
    public static Object newInstance(Class<?> componentType, int length)
                throws NegativeArraySizeException {
            return newArray(componentType, length);
        }
    

    调用任意方法和构造器

    • Field类的get方法可以查看一个对象的字段
    • Method类可以通过invoke方法调用包装在当前Method对象中的方法,invoke的参数和返回值必须是Object类型,Obejct invoke(Object obj, Object... args),如果是静态方法,第一个参数可以是null
    import java.lang.reflect.*;
    
    public class MethodTableTest
    {
       public static void main(String[] args) throws Exception
       {
          // get method pointers to the square and sqrt methods
          Method square = MethodTableTest.class.getMethod("square", double.class);
          Method sqrt = Math.class.getMethod("sqrt", double.class);
    
          printTable(1, 10, 10, square);
          printTable(1, 10, 10, sqrt);
       }
    
       public static double square(double x)
       {
          return x * x;
       }
    
       public static void printTable(double from, double to, int n, Method f)
       {
          System.out.println(f);
          double dx = (to - from) / (n - 1);
          for (double x = from; x <= to; x += dx)
          {
             try
             {
                double y = (Double) f.invoke(null, x); //这里用到invoke
                System.out.printf("%10.4f | %10.4f%n", x, y);
             }
             catch (Exception e)
             {
                e.printStackTrace();
             }
          }
       }
    }
    
    
    • Constructor类,获取类的构造器,构造对象
    Class cl = Random.class;
    Constructor cons = cl.getConstructor(long.class);
    Object obj = cons.newInstance(42L);
    

    反射有什么用 https://www.zhihu.com/question/377483107

    相关文章

      网友评论

          本文标题:Java核心技术(卷I) 11、反射

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