JAVA 基础 之 反射

作者: 蓉漂里的小白 | 来源:发表于2018-12-11 23:33 被阅读18次

    一:Class类的使用


    1: Class 类介绍

        在Java中除了基本数据类型和静态的东西都是对象,都是Java.lang.class的对象,

        在上面的Code我们创建了一个Food类,实例化了一个food的对象, 其实Food这个类也是一个对象,是Java.lang.class的对象 。我们知道,通过new A(A任意一个类)来得到一个A类的对象,同样任意一个类都是class的对象,我们也可以获取到Class的对象

        获方式如下:

              1:Class c1 = Food.class()

              2:  Class c2 = food.getClass();

                3: Classc3 = Class.forName(“com.xxx.xx”);

    2:动态加载类

          程序都分为编译期和运行期2个时期。

          编译期:是指编译器将源代码翻译为机器能识别的代码,java为编译为jvm认识的字节码文件。 

          运行期:则是指java代码的运行过程。

            在我们的FactoryFood中,我们需要根据实际情况引很多个类,而且我们需要编译期编译很多类,但实际可能只会用到1,2个类。

          在我们的DynamicFactory中,我们没有引入任何实体类,而是由程序动态的加载和创建对象。需要什么类就传入什么类的包.类名即可

    总结:通过动态加载类的方式,我们可以随意的添加和删除类而不需要重新编译。然而静态类却不行,每次新增类都需要重新编译程序。

    二:获取方法信息


        下面让我们通过反射的方式来获取类的名称,方法,变量,函数的参数,返回值

        getMethods():获取所有的public方法,包括从父类继承过来的,如上面的wait方法(在java中我们新建的类默认继承Object,所以Food类里面就获取到了warit方法)

        getDeclareMethods():获取类自己申明的方法包括(public, private, protect)通过上面的输出我们可以看出来,使用getDeclareMethods获取到了updateFood(private)但是没有获取到wait(从父类继承的)

    三:获取成员变量


        前面我们介绍了方法的获取方法,那成员变量依然可以获取,而且成员变量也是对象是Java.lang.Field的对象,

        我们先在类中添加一个public Character character的成员变量

        下面演示获取成员变量信息的例子

        getFields()只能获取public的成员变量,在输出信息中,我们可以看到只输出了一个character的成员变量

        getDeclareField()可以获取该类所有自己声明的成员变量包括public的,private的和protected,以及default类型的

    四:获取构造函数信息


        类是对象,成员变量是对象,同样构造函数也是对象,是Java.lang.Constructor的对象。

        下面让我们来获取构造函数的参数列表和参数类型

        getConstructors():获取所有的public的构造函数(也有private的构造函数,比如:单例模式中就存在)

        getDeclareConstructors():获取所有自己申明的构造函数(构造函数只能是自己申明的)

        同样我们也可以通过getInterface, getSuperClass获取接口和父类

        注:只要我们得到类的类型,我们就可以得到该类的所有信息

    五:方法的反射


        前面讲述了一大堆获取方法,变量,参数,返回值的操作,接下来就来实际操作通过反射来调用我们的方法,指令method.invoke();

        首先,我们要调用方法就要先获取方法信息,要获取方法信息就要获取类信息,就是获取类类型

        首先我们在Food类中添加如下三个方法:

        然后我们来反射调用这三个方法:

        在上面的code中,我们先调用setDefaultName来给Food命名,然后在调用getFoodName来检查我们是否成功的通过反射完成了设值,然后我们再调用有参数的方法setFoodNumber,来重新设置name和 number然后再调用getFoodName来检查我们是否成功的通过反射完成了设值

        从输出的信息,我么可以得知我们成功的通过反射来完成了Food方法的调用,但是我们发现,第一次的输出是null,因为我们的第一次调用的函数是无返回值的。

        注:当有返回值,Object为具体的返回值,无返回值时,Object为null函数有参数时,调用时传入具体的参数,多个参数,传入一个Object数组;无参数调用时不传参数

    深入理解:

        反射是编译之后的操作,前面的文章我们讲泛型,说泛型是编译期的安全检查,那我们就可以通过反射来给泛型插入数据而不出现编译错误:

        通过上面的输出结果我们可以发现我们定义了String的ArrayList,添加了一个”First”,这时候size是1,然后又通过反射来添加一个22到ArrayList中,输出的 Size是2。所以通过反射可以绕过泛型的检查(因为编译器在编译期会做泛型擦除)。

    相关文章

      网友评论

        本文标题:JAVA 基础 之 反射

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