反射的引入以及原理

反射的作用

反射可以使我们通过外部文件配置,在不修改源码的情况下,来控制程序,也符合设计模式ocp的原则(在不修改源码的条件下,扩容功能)

简单示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.zss.reflact;

/**
* @author zss
*/
public class Cat {
public void hi(){
System.out.println("你好啊小猫猫");
}
public void cry(){
System.out.println("小猫咪哭泣");
}

}

image-20220321151517509

我想要通过配置文件另外一个程序调用Cat的对象,并且调用其cry方法,接下来我们只需要通过更改配置文件的method方法指向的方法即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.zss.reflact;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Properties properties=new Properties();
properties.load(new FileReader("src/com/zss/reflact/test.properties"));
String classPath=properties.getProperty("class");
String method=properties.getProperty("method");
//首先我们得到了类名称以及方法,但是在这里我们无法创建新的类和调用方法
//使用反射机制,第一步加载类,返回Class了类型的对象clas
Class clas=Class.forName(classPath);
//通过clas得到加载类,Cat的实例对象
Object o=clas.newInstance();
System.out.println("运行类型为"+o.getClass());
//通过clas得到加载类的方法,在反射机制中将方法视为对象(万物皆对象)
Method method1=clas.getMethod(method);
//通过方法对象类调用对象
method1.invoke(o);

}
}

image-20220321152608448

反射机制

反射机制允许程序在执行期间借助ReflectionAPI得到任何类的内部信息(比如成员变量,构造器,成员方法等),并能操作对象属性以及方法。加载完类之后,在堆中产生了一个Class类型的对象(一个类只能有一个),这个对象包含类的完整结构信息,通过这个对象得到类的结构,这个对象就像一面镜子,通过镜子看到类的结构

image-20220321154203831

  1. 首先,通过Javac 方法编译文件,编译成为.class的文件,包含其方法,构造器等信息。
  2. 当我们在运行阶段new一个对象的时候,类会进行加载,将.class字节码文件通过类加载机制加载到class类对象堆中,以数据结构的方式进行存储,而且方法等不为一个,所以以数组的方法进行保存。
  3. 而生成的Cat对象,知道他是属于哪一个class对象的
  4. 而我们得到class对象时,我们可以创建对象,调用方法等等