Java的反射机制是指在程序的运行状态中,可以构造任意一个类的对象,可以得到任意一个对象所属的类的信息,可以调用任意一个类的成员变量和方法,可以获取任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。
反射机制的优点是可以实现动态创建对象和编译(即动态编译),特别是在J2EE的开发中,反射的灵活性表现的十分明显。例如,一个大型的软件,不可能一次就把程序设计的很完美, 当这个程序编译、发布上线后,如果需要更新某些功能,我们不可能要用户把以前的软件卸载,再重新安装新的版本。这时,如果采用静态编译,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制,程序可以在运行时动态的创建和编译对象,不需要用户重新安装软件,即可实现功能的更新。
认识Class类
Java程序的运行机制,JVW编译.java 文件生成对应的.class文件,然后再将.class文件加载到内存中执行。在执行.class文件的之后可能需要用到其他类(其他.class文件内容),这个时候就需要获取其他类的信息(反射)。JVM在加载.class文件时,会产生一个java.lang.Class对象代表改.class字节码文件,从该Class对象中可以过的类的信息。因此想要完成泛着操作,就必须先认识Class类
Class是JDK定义的类,它提供了很多方法,通过调用Class类的成员方法可以获取Class对象中的信息(.class文件中的类的信息)。Class类的常用方法如下表
例如(方法一)我们之前的数据库
这里放的都是字节码文件
以前我们创建对象,对象调用属性,对象调用方法
现在我们就可以通过反射来进行
我们可以通过三种方法获得数据类型
第一种
第一种和其他两种
运行结果
获得的类都是Student
然后我们换一个将第二种方法的Student变成Teacher
运行结果
通过无参构造函数实例化对象
如果想通过Class类实例化其他类的对象,则可以使用newInstance()方法,但是必须要保证被实例化的类中存在一个无参构造方法。接下来通过一个案例演示Class类通过无参构造实例化对象。安装新的版本。这时,如果采用静态编译,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制,程序可以在运行时动态的创建和编译对象,不需要用户重新安装软件,即可实现功能的更新。
例如:在我们的老师类中有一个无参的构造方法
然后刚刚我们通过Student2得到了老师的这个类型
然后我们就可以通过反射来创建对象,就是通过类对象调用newInstance
还可以用之前的其他方法来
或者
通过有参构造实例化对象
如果类中没有无参构造方法,则可以通过有参构造方法实例化对象。通过有参构造方法实例化对象时,需要明确调用的构造方法,并传递相应的参数。通过有参构造方法实例化对象的操作步骤如下:
(1)通过Class类中的getConstructors()方法获取本类中的全部构造方法。
(2)向构造方法中传递一个对象数组,对象数组里面包含构造方法中所需的各个参数。
(3)通过Constructor类实例化对象。
8.3.2通过有参构造实例化对象
上述操作步骤中使用了Constructor类, Constructor类用于存储本类的构
造方法。Constructor类的常 用方法如下表。
例如
上面的是只有一个方法,我们给上面的方法再加上三个方法,相当于拥有四个方法
这个时候我们cons[0]运行就是错的,因为它会默认的排序,从小到大进行排序。我们的数组下标是0的时候,其实只有name的方法。只有下标为3才会是有四个参数的方法
下标为0的方法
反射的作用
在实际开发中,通过反射可以得到一个类的完整结构,包括类的构造方法、类的属性、类的
方法,这就需要使用到java.lang.reflect包中的以下几个类:
(1) Constructor: 表示类中的构造方法。
(2) Field: 表示类中的属性。
(3) Method: 表示类中的方法。
获取所实现的全部接口
要取得一个类所实现的全部接口,必须使用Class中的getInterfaces()方法。getInterfaces()方法声明如下:public Class[] getInterfaces();getInterfaces()方法返回- -个Class类的对象数组,调用Class类中的getName(方法可以取得类的名称。
例如
首先定义一个接口:一个是颜色,一个是类型
然后定义另外一个接口
我们在另外一个类中查找USDisk接口实现的接口
运行结果
然后给它再加一个接口
然后遍历的时候就会得到两个接口的名字
获取全部方法
要取得一个类中的全部方法,可以使用Class类中的getMethods()方法,该方法返回一个Method类的对象数组。如果想要进一步取得方法的具体信息,如方法的参数、抛出的异常声明等,就必须依靠Method类。可以取得类的名称。
例如:获得程序员里面的方法
还可以获得修饰符和返回类型
8.4.3获取全部属性
在反射操作中也可以获取一个类中的全部属性,但是类中的属性包括两部分,从父类继承的属性,本类定义的属性。因此,在获取类的属性时也有两种不同的方式,分别如下:
(1)获取实现的接口或父类中的公共属性: public Field[] getFieldsthrows SecurityException。
(2)获取本类中的全部属性: public Field[] getDeclaredFieldsthrows SecurityException。
例如:查找Programmer
运行结果
或者我们写一个父类
然后再写一个子类
只能获得自己的属性,不能得到从父类继承的属性
获得所有的属性,注意,给父类属性的前面加public,如果不加就会一个都得不到