一:反射的引出
1:问题
比如我们给出一个student类 其方法show(),我们将其写入配置文件中;现在我们来一个新的需求说是要改变重写一个show()方法 show()2,那么如何在不修改源码的情况下进行修改,这时我们通过反射就可以完成
2:过程
student类:
public class Student {public void show(){System.out.println("is show()");}
}
配置文件以txt文件为例子(pro.txt):
className = cn.fanshe.Student
methodName = show
测试类:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;/** 我们利用反射和配置文件,可以使:应用程序更新时,对源码无需进行任何修改* 我们只需要将新类发送给客户端,并修改配置文件即可*/
public class Demo {public static void main(String[] args) throws Exception {//通过反射获取Class对象Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"//2获取show()方法Method m = stuClass.getMethod(getValue("methodName"));//show//3.调用show()方法m.invoke(stuClass.newInstance());//stuClass.newInstance() 获取当前类的对象 //以前:对象.方法();现在:方法名.(对象)}//此方法接收一个key,在配置文件中获取相应的valuepublic static String getValue(String key) throws IOException{Properties pro = new Properties();//获取配置文件的对象FileReader in = new FileReader("pro.txt");//获取输入流pro.load(in);//将流加载到配置文件对象中in.close();return pro.getProperty(key);//返回根据key获取的value值}
}
控制台输出:
is show()
需求:
当我们升级这个系统时,不要Student类,而需要新写一个Student2的类时,这时只需要更改pro.txt的文件内容就可以了。代码就一点不用改动
要替换的student2类:
public class Student2 {public void show2(){System.out.println("is show2()");}
}
配置文件更改为:
className = cn.fanshe.Student2
methodName = show2
控制台输出:
is show2();
3:总结
可以看到我们只是改了配置文件,而并没有去改变源码
二:反射是什么
JAVA反射机制是在运行状态中
对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
三:反射的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
(要想解剖一个类,必须先要获取到该类的字节码文件(.class)对象(class)。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.)
五:关于class对象和class类
1:class对象
Class对象的由来是将class文件读入内存,并为之创建一个Class对象
2:class类
- 代表一个类,是Java反射机制的起源和入口
- 用于获取与类相关的各种信息, 提供了获取类信息的相关方法
- Class类继承自Object类
- Class类是所有类的共同的图纸
- 每个类有自己的对象,同时每个类也看做是一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应方法取出相应 的信息:类的名字、属性、方法、构造方法、父类和接口。
- Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)
- Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。没有公共的构造方法,方法共有64个太多了。
3:获取class对象方法
通过Class.forName(“全类名”) (最常用的方法)
try {Class<?> perClazz = Class.forName("reflect_fanshe.Person");System.out.println(perClazz);} catch (ClassNotFoundException e) {e.printStackTrace();}
4:根据反射入口对象(class)获取类的各种信息
(1):perClazz.getMethods() 获取此类的所有public方法(父类的,实现接口的,自己的)
Class<?> perClazz = null;try {perClazz = Class.forName("reflect_fanshe.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Method[] methods = perClazz.getMethods();//遍历所有方法for (Method method : methods) {System.out.println(method);}}
(2):获取当前类(只有本类的)的所有方法和属性,包括私有的
(3):可以获取当前类的对象,并通过对象调用类的方法
(4):通过反射获取对象的实例,并操作对象
class.newInstance() ,并强转类型,然后就可以操作对象了,主要是调用方法。
六:反射的使用场景
- java编码时知道类和对象的具体信息,此时直接对类和对象进行操作即可,无需反射
- 如果编码时不知道类或者对象的具体信息,此时应该使用反射来实现
- 比如类的名称放在XML文件中,属性和属性值放在XML文件中,需要在运行时读取XML文件,动态获取类的信息在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息
参考自