1.什么是反射,有啥用?
前言: 最开始接触反射的时候,我是真的很懵,不明白反射到底是个啥,是干什么的,其实本来很简单,只是老师也没有细讲,我也没有用心听,后来看了老韩的Java基础课,终于明白了。
简单来说,反射主要是用来根据配置文件来 动态 创建 类的实例对象 和动态使用 类的实例对象的方法 ,这里的 动态 是啥?想想我们平时创建类的实例对象是直接使用关键词 new 来创建的,但是这是基于我们知道我们自己要使用哪个类为前提,就是知道类的名字,比如我们要使用Dog类,我们知道它的名字是Dog,直接俄 new 一个Dog类就好了,可是我现在要你写一个程序,要使用一个类的一个方法,但是这个类不是一个固定的类,可能是Dog类,也可能是任何一个类,里面的方法当然也是跟着类一起动态变化的,显然你不知道我具体要你使用哪个类,我只通过配置文件告诉你这个类的全类名和要使用的类的方法的名字,你可以通过读取这个配置文件把这两个参数读入你的程序中,但是你会发现你读入的只不过是两个字符串,只是类名的字符串和方法名的字符串。就像下面这样,你能根据这两个字符串创建出我想要你创建的类并且执行我想要你执行的方法吗?
public class ReflectionTest {
public static void main(String[] args) throws Exception{
Properties properties = new Properties();
properties.load(new FileInputStream("config.properties"));
//读取类名
String className = properties.getProperty("preClass");
//读取方法名
String methodName = properties.getProperty("preMethod");
}
}
我现在就是不告诉你配置文件中 preClass 和 preMethod 的具体内容是什么,就是让你根据配置文件创建对象并使用方法,很显然,你要是不知道反射,肯定不知道从何下手, 哈哈哈哈哈。。。。
2.根据类的名字字符串创建类对像
类对象? 这可不是我们最后要创建的类的实例,而是 Class 类的实例,刚学Java的时候老师就告诉我们 Java 一切皆对象,所有类本身也是Class的一个具体实例对象。我们可以通过 Class 的静态方法 forName, 拿到这个字符串所对应的类的 类对象
Class cla = Class.forName(className);
说来说去都晕了,最后拿到一个不知道有什么用的类对象,我们为什么要创建它呢,请往下看↓
3. 根据类的类对象创建类的实例
上回中我们拿到了类的类对象,这回我们调用它的 newInstance 方法创建类的实例,类对象就是起了这个作用
Object o = cla.newInstance();
好奇的你会注意到我们使用的 Object 的引用来接收类的实例,这显然是因为我们不知道类的名字,而 Object 类恰好是所有类的父类,我们可以通过这样的方式拿到实例对象的上转型对象,我们现在已经很接近我们的最终目标了,请继续👇
4. 通过我们读取的方法名字创建方法实例对象
我们一般是通过对象后面打一个点IDE就会自动显示里面的所有可调用方法,而现在我们不仅不知道方法的名字而且我们拿到的是上转型对象,根本无法看到子类对象的方法。这可如何是好?
哈哈哈,前面我们讲过 一切皆对象,方法也是对象,下面是如何得到这个方法的实例。
Method method = cla.getMethod(methodName);
没错,我们是通过类对象的 getMethod 方法得到方法实例的,可见,类对象里面存的是类的属性以及方法,我们可以通过它获取方法实例
不知道你有没有感觉 一切皆对象 这句话是多么高深莫测。。。
5. 通过方法的实例对象和类的实例对象的上转型对象调用方法
System.out.println(o);
System.out.println(method);
method.invoke(o);//这一条是关键
没错,我们使用了 invoke 方法把实例对象作为参数,方法实例作为调用者,别问我为什么,因为就是这样使用的,具体了解 invoke 方法请自行百度。
6. 最后我们看一下输出
ltd.itlover.testclass.Dog@4554617c
public void ltd.itlover.testclass.Dog.say()
汪,汪汪~~~
现在你终于知道我要你调用的是Dog类的say方法,方法的内容就是汪汪叫两下,但是你之前并不知道,你成功的通过反射技术执行了它,虽然并不知道它到底是什么。
7. 感言
至此,你已经入门Java反射了。要入门一种技术我们就要首先了解技术是干啥的以及主要的应用场景,这是熟练掌握技术和创新的前提。要了解就要了解到关键,虽然不是很复杂,但是却很难捕捉到,一旦掌握了关键点,就没有什么可怕了。
然而事实是很少有人会跟你细致的讲关键,还是得自己多学习多思考
最后献上源码和配置文件
测试类
public class ReflectionTest {
public static void main(String[] args) throws Exception{
Properties properties = new Properties();
properties.load(new FileInputStream("config.properties"));
//读取类名
String className = properties.getProperty("preClass");
//读取方法名
String methodName = properties.getProperty("preMethod");
Class cla = Class.forName(className);
Object o = cla.newInstance();
Method method = cla.getMethod(methodName);
System.out.println(o);
System.out.println(method);
method.invoke(o);
}
}
使用的类
public class Dog {
public void say(){
System.out.println("汪,汪汪~~~");
}
}
配置文件config.properties
preClass = ltd.itlover.testclass.Dog
preMethod = say
最后记得配置文件要放在项目根目录下