java-反射

58 阅读2分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第一篇文章,点击查看活动详情

引入

在清楚一个java类内容的情况下,我们可以直接用new对象的方式来使用类,那么仅仅知道类的类名,能否动态得到类的定义信息,包括哪些方法,属性等? 答案:用反射。

概念

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。

如何做到的呢?

当一个字节码文件加载到内存的时候,jvm会对该字节码进行解剖,然后创建一个对象的Class对象,把字节码文件的信息全部都存储到该Class对象中,我们只要获取到Class对象,我们就可以使用字节码对象设置对象的属性或者调用对象的方法等操作

API

Java反射相关的类主要包括Class   类型,Constructor 构造方法,Method 方法,Field 属性。

  • Class:

        //得到一个class类型对象有三种方式
        //1.可以通过对象名.getClass获得
        Object obj=new Object();
        Class objClass = obj.getClass();

        //2.类名.class
        Class cls=String.class;

        //3.Class.forName
        Class cls2 = Class.forName("java.lang.String");

  • Constructor

        // 得到一个Class类型对象,Book是一个自己写的类,这个位置可以试任何类。
        Class cls = Book.class;

        // 调用方法->得到构造方法 包括私有的构造
        Constructor[] cons = cls.getDeclaredConstructors();

        // 遍历数组,输出结果
        for(Constructor c : cons) {
           System.out.println(c.getName() + " getParameterCount() :" + c.getParameterCount() + " getParameters():"+ c.getParameters());
        }

        System.out.println("**********************");

        // 调用方法->得到构造方法 ->公共的构造方法
        Constructor[] cons2 = cls.getConstructors();

        // 遍历数组,输出结果
        for (Constructor c : cons2) {
           System.out.println(c.getName() + " getParameterCount() :" + c.getParameterCount() + " getParameters():"+ c.getParameters());
        }
  • Field

        // 得到一个Class类型对象
        Class cls = Animail.class;

        // 调用方法->所有属性
        Field[] fields = cls.getDeclaredFields();

        // 遍历数组,输出结果
        for (Field field : fields) {
            System.out.println(field.getName());
        }

        System.out.println("**********************");

        // 调用方法->公共属性
        Field[] fields2 = cls.getFields();

        // 遍历数组,输出结果
        for (Field field : fields2) {
            System.out.println(field.getName());
        }
  • Method

        // 得到一个Class类型对象
        Class cls = Book.class;

        // 调用getDeclaredMethods方法->得到这个类方法->私有,公共,受保护的等,静态等,但是没有父类的方法
        Method[] methods = cls.getDeclaredMethods();

        // 遍历数组,输出结果
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        
        System.out.println("**********************");

        // 调用getMethods方法->得到这个类实例和静态,包括从父类继承而来的等方法,但是没有私有和保护的方法
        Method[] methods2 = cls.getMethods();

        // 遍历数组,输出结果
        for (Method method : methods2) {
            System.out.println(method.getName());
        }
        
        System.out.println("*********使用反射调用某个public方法*************");

       // 返回Method->setBookname
       Method m1 = cls.getDeclaredMethod("setBookname", String.class);
       Object obj = cls.newInstance();
       
       // 调用这个方法 第一个参数是指定类型的那个对象,第二个参数是方法的实际参数的值
       m1.invoke(obj, "西游记");
       System.out.println(obj);

       System.out.println("*********使用反射调用某个private方法*************");
       
       Method m2 = cls.getDeclaredMethod("test4", null);
       Object obj1 = cls.newInstance();

       //可以访问私有的方法
       m2.setAccessible(true);

       //调用私有无参数的方法
       m2.invoke(obj1, null);
       System.out.println(obj1);