反射就是把Java类中的各个成员映射成一个个的Java对象。
即在运行状态中
1、对于任意一个类,都能知道这个类的所有属性和方法。
2、对于任意一个对象,都能调用它的任意一个属性和方法。
这种动态获取信息以及动态调用对象方法的功能叫做Java的反射机制。
1、对象创建过程
为什么在介绍反射的时候需要先介绍对象创建过程?
通过对象创建,引出Class对象
- 通过javac命令把Java源代码编译成class文件。
- 类加载器加载class文件到内存
- 类元信息存放在方法区。(类元信息:类、方法等字节码信息)
- 创建类对应的Class对象,放在堆区。(每个类只会创建一个Class对象,作为方法区类的数据结构的接口。jvm创建对象前,会先检查类是否被加载,寻找类对应的Class对象)
2、反射的原理
- 反射机制允许程序在执行期间借助于ReflectionApi取得任何类的内部信息(比如成员变量、构造器、成员方法等),并能操作对象的属性和方法。
- 加载完类后,在队中就产生了一个Class对象,这个对象包含了类的完整结构信息。通过这个对象可以得到类的结构。
3、反射的作用
- 在运行时判断任意一个对象所属的类
- 在运行时构造任何一个类的对象
- 在运行时得到任意一个类所具有的的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理
4、反射的相关类
Java反射机制的实现主要借助以下4个类:
- java.lang.Class:代表一个类,Class对象是类被加载后,在堆中的对象
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造方法
5、反射的使用
5.1 如何获取Class对象
- 类.class
- 对象.getClass()
- Class.forName(全类名)
package reflect;
/**
* 获取Class对象
*
* @author zhao.hualuo
* Create at 2022/4/28
*/
public class GetClass {
public static void main(String[] args) throws ClassNotFoundException {
//类.class
Class<GetClass> aClass = GetClass.class;
System.out.println(aClass.getName());
//对象.getClass()
GetClass getClass = new GetClass();
Class<? extends GetClass> bClass = getClass.getClass();
System.out.println(bClass.getName());
//Class.forName(全类名)
Class<?> cClass = Class.forName("reflect.GetClass");
System.out.println(cClass.getName());
}
}
5.2 通过Class对象进行反射
package reflect;
import java.lang.reflect.Method;
/**
* 反射Demo
*
* @author zhao.hualuo
* Create at 2022/4/28
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
//1、获取Class对象
Class<ReflectDemo> demoClass = ReflectDemo.class;
//2、利用Class对象获取对象全部信息
System.out.println("get " + demoClass.getClassLoader());
System.out.println("get " + demoClass.getConstructors());
System.out.println("get " + demoClass.getMethods());
System.out.println("get " + demoClass.getMethod("sayHello", String.class));
System.out.println("get " + demoClass.getMethod("sleep", int.class));
System.out.println("get " + demoClass.getFields());
System.out.println(" ");
//3、利用Class对象可任意调用类方法
ReflectDemo demo = demoClass.newInstance();
Method method = demoClass.getMethod("sayHello", String.class);
method.invoke(demo, "张三");
Method[] methods = demoClass.getMethods();
methods[1].invoke(demo, 7);
}
public static void sayHello(String name) {
System.out.println("hello " + name);
}
public static void sleep(int num) {
System.out.println("sleep " + num + " hour");
}
}
执行结果:
"D:\Program Files\Java\jdk1.8.0_281\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:62399,suspend=y,server=n -javaagent:C:\Users\zhao.hualuo\AppData\Local\JetBrains\IdeaIC2021.3\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "D:\Program Files\Java\jdk1.8.0_281\jre\lib\charsets.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\deploy.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\access-bridge-64.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\cldrdata.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\dnsns.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\jaccess.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\jfxrt.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\localedata.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\nashorn.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\sunec.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\sunjce_provider.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\sunmscapi.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\sunpkcs11.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\ext\zipfs.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\javaws.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\jce.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\jfr.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\jfxswt.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\jsse.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\management-agent.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\plugin.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\resources.jar;D:\Program Files\Java\jdk1.8.0_281\jre\lib\rt.jar;D:\CodeWorkspace\Demo\target\production\Demo;D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.3\lib\idea_rt.jar" reflect.ReflectDemo
Connected to the target VM, address: '127.0.0.1:62399', transport: 'socket'
get sun.misc.Launcher$AppClassLoader@18b4aac2
get [Ljava.lang.reflect.Constructor;@4d591d15
get [Ljava.lang.reflect.Method;@65ae6ba4
get public static void reflect.ReflectDemo.sayHello(java.lang.String)
get public static void reflect.ReflectDemo.sleep(int)
get [Ljava.lang.reflect.Field;@48cf768c
hello 张三
sleep 7 hour
Disconnected from the target VM, address: '127.0.0.1:62399', transport: 'socket'
Process finished with exit code 0
获取的methods为:
6、反射的优化
Method、Field、Constructror对象都有setAccessible()方法。
setAccessible():启用或者禁用访问安全检查。true代表取消访问检查,false代表执行访问检查
关闭安全检查可以提高反射效率