Java的反射机制

  不想说话...........反正Java的反射很好用(>人<;)

  所以什么是反射?

    反射就是在运行时才知道要操作的类是什么并且可以在运行时获取类的完整构造,并调用对应的方法。

Class类的使用

 

1.Class类

1) 在面向对象的世界里,万事万物皆对象。

Java语言中,静态的成员、普通数据类型也是对象,类是Java.lang.Class类的实例对象

  (首先定义一个类Foo,再new一个实例对象foo1,Foo 这个类也是一个实例对象,Class类的实例对象 

  任何一个类都是Class类的实例对象,该怎么表示呢U•ェ•*U

    第一种表达方式:Class c1  = Foo.class; // 说明任何一个类都有一个隐含的静态成员变量class

      第二种表达方式:Class c2  = foo1.getClass(); // 已经知道该类的对象通过getClass方法

      第三种表达方式:Class c3  = Class.forName("com.daxian.Reflect.Foo")

  

我们完全可以通过类的类类型创建该类的对象实例——>通过c1 or c2 or c3创建Foo 的实例:
   
Foo foo2 = (Foo) c1.newInstance();
 

Java动态加载类

  

2) Class.forName("类的全称")

  不仅表示了类的类类型,还代表了动态加载类

  注意区分编译和运行

  编译时刻加载类是静态加载类,运行时刻加载类是动态加载类

   new 创建对象 是静态加载类,在编译时刻就需要加载所有可能使用到的类

方法的反射

  1)如何获取某个方法

    方法的名称和方法的参数列表才能唯一决定某个方法

    通过java.lang.reflect.Method类,获取方法对象,一个成员方法就是一个Method对象

    getMethod() 方法获取的是所有的public函数,包括父类继承而来的

    getDeclaredMethods() 获取的是所有该类自己声明的方法,不问访问权限
     Method[] ms = c.getMethods();// c.getDeclaredMethods()
        for(int i=0 ;i<ms.length;i++){
            //得到方法的返回值类型
            Class returnType = ms[i].getReturnType();
            System.out.print(returnType.getName()+" ");
            //得到方法的名称
            System.out.print(ms[i].getName()+"(");
            //获取参数类型——>得到的是参数列表的类型的类类型
            Class[] paramTypes = ms[i].getParameterTypes();
            for(Class class1 : paramTypes){
                System.out.print(class1.getName()+",");
            }
            System.out.println(")");

        }


  2)方法反射的操作

    method.invoke(对象,参数列表)

            Method m = c1.getMethod("print", int.class, int.class);

            //方法的反射操作
            //a1.print(10,20);方法的反射操作是用m对象来进行方法调用 和 a1.print调用的效果一样
            //方法如果没有返回值则返回null,有返回值返回具体的返回值
            //Object o =m.invoke(a1,new Object[]{10,20});
            Object o =m.invoke(a1,10, 20);        

 

普通数据类型也有类类型

   3)为什么要用方法的反射

    why?指定方法名称调用方法

    举个实际应用的案例——>通过标准的JavaBean的属性名获取其属性值

    BeanUtil 类

  4)通过class,Method来认识泛型的本质

 

成员变量的反射

     成员变量也是对象,通过java.lang.reflect.Field

       Field 类封装了关于成员变量的操作

    getFields() 方法获取的是所有的public的成员变量的信息

getDeclaredFields() 获取的是该类自己声明的成员变量的信息

        Field[] fs = c.getDeclaredFields();
        for(Field field : fs){
            //得到的是成员变量的类型的类类型,也就是说如果成员变量是int类型,那么这里就是int.class
            Class fieldType = field.getType();
            String typeName = field.getName();
            //得到成员变量的名称
            String fieldName = field.getName();
            System.out.println(typeName + " " + fieldName);
        }    

构造函数的反射 

  构造函数也是对象
  * java.lang.Constructor中封装了构造函数的信息
  * getConstructors获取所有的public的构造函数
  * getDeclaredConstructors得到所有的构造函数
        Constructor[] cs = c.getDeclaredConstructors();
        for(Constructor constructor : cs){
            System.out.print(constructor.getName() + "(");
            Class[] paramTypes = constructor.getParameterTypes();
            for (Class class1 : paramTypes){
                System.out.print(class1.getName()+",");
            }
            System.out.println(")");
        } 
 

通过Java反射机制了解集合泛型的本质

public class MethodDemo4 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();

        ArrayList<String> list1 = new ArrayList<>();
        Class c1 = list.getClass();
        Class c2 = list1.getClass();
        System.out.println(c1 == c2);
        /*现在不能用for(String string : list1)来遍历了*/

        //反射的操作都是编译之后的操作

        /**
         * c1 == c2 为true  说明编译之后集合的泛型是去泛型化的
         * Java中集合的泛型,是防止错误输入的,只在编译阶段有效
         * 绕过编译就无效了
         * 验证:我们可以通过方法的反射来操作,绕过编译
         */
        try {
            Method m = c1.getMethod("add",Object.class);
            m.invoke(list1,100);
            System.out.println(list1.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
原文地址:https://www.cnblogs.com/MoisAbby/p/8456715.html