引言
反射库( reflection library) 提供了一个非常丰富且精心设计的工具集, 以便编写能够动
态操纵 Java 代码的程序。这项功能被大量地应用于 JavaBeans 中, 它是 Java组件的体系结构。
什么是反射?
(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到类对象之后,再通过类对象进行反编译,从而获取对象的各种信息。
(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁
反射,指能够分析类信息的能力叫做反射。
反射机制的功能极其强大,在下面可以看到, 反射机制可以用来:
1、在运行时分析类的能力。
2、在运行时查看对象, 例如, 编写一个 toString 方法供所有类使用。
3、实现通用的数组操作代码。
4、利用 Method 对象, 这个对象很像中的函数指针
什么是类的信息?
简单的来说比如 属性、方法、构造器等等
那么一个新的问题就来了,我们明明可以通过new 一个对象来获取类信息,那么我们为什么要使用反射呢?
以 servlet 为例,在 servlet 中我们写过JBDC类,在这个类当中我们引入了一个mysql.jar包,那么这个jar包是怎么起作用的呢,请大家注意,我们的servlet类当中没有main方法,那我们的servlet类是如何启动的呢?如何加载到我们的JVM当中呢?其中就用到了反射。
反射如何工作?
在理解反射的工作原理之前,让我们先了解一下类的生命周期
1、当我们编写一个java的源文件后,经过编译会生成一个后缀名为class的文件,这种文件叫做字节码文件。只有这种字节码文件才能够在java虚拟机中运行。
2、 java类的生命周期就是指一个class文件从加载到卸载的全过程。一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段,
其中,反射就发生在加载和初始化中。反射的原理在下面的图里,我就不细说了
反射获取类信息的方式
1、(类名).class
2、(类名).getClass()
3、Class.forName(全类名)
手写反射实例
实例1
Person类
public class Person {
public void sleep(){
System.out.println("我想睡觉,,,");
}
}
配置文件
className = Person
methodName = sleep
测试类
public class PersonTest {
public static void main(String[] args) throws Exception {
// 将 配置文件加载进内存
Properties properties = new Properties();
ClassLoader classLoader = PersonTest.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("pro.properties");
properties.load(inputStream);
// 获取配置文件当中的变量
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
// 加载进内存
Class class1 = Class.forName("com.servlet."+className);
// 创建对象
Object object = class1.newInstance();
// 获取方法对象
Method method = class1.getDeclaredMethod(methodName);
method.setAccessible(true);
//执行方法
method.invoke(object);
}
}
测试结果:
实例二
Student 类
public class Student {
private String name;
private int age;
private String address;
private Student() { }
public Student(String name) {
this.name = name;
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
测试类
package com.servlet;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author 流星
*/
public class StudentTest {
public static void main(String[] args) throws Exception {
/**
* 获取变量
**/
Class<?> student = Class.forName("com.servlet.Student");
System.out.println("--------------类变量----------------");
Field[] fields1 = student.getDeclaredFields();
for (Field field : fields1) {
System.out.println(field);
}
/**
* 获取方法
**/
System.out.println("--------------类方法----------------");
Method[] methods1 = student.getDeclaredMethods();
for (Method method : methods1) {
System.out.println(method);
}
/**
* 获取构造器
**/
System.out.println("--------------构造器----------------");
//私有方法,进行暴力反射:setAccessible(true)
Constructor<?> constructor1 = student.getDeclaredConstructor();
constructor1.setAccessible(true);
System.out.println(constructor1);
Constructor<?> constructor2 = student.getDeclaredConstructor(String.class);
System.out.println(constructor2);
Constructor<?> constructor3 = student.getDeclaredConstructor(String.class, int.class, String.class);
System.out.println(constructor3);
/**
* 初始化对象
**/
System.out.println("-------------输出对象---------------");
Object stu1 = constructor1.newInstance();
Object stu2 = constructor2.newInstance("宫");
Object stu3 = constructor3.newInstance("离", 27, "璃月");
Method setName = student.getDeclaredMethod("setName", String.class);
Method setAge = student.getDeclaredMethod("setAge", int.class);
Method setAddress = student.getDeclaredMethod("setAddress", String.class);
Method getName = student.getDeclaredMethod("getName");
Method getAge = student.getDeclaredMethod("getAge");
Method getAddress = student.getDeclaredMethod("getAddress");
System.out.println(getName.invoke(stu3) + " " + getAge.invoke(stu3) + " " + getAddress.invoke(stu3));
System.out.println("-------------输出对象---------------");
setName.invoke(stu1, "樱");
setAge.invoke(stu1, 22);
setAddress.invoke(stu1, "稻妻");
System.out.println(getName.invoke(stu1) + " " + getAge.invoke(stu1) + " " + getAddress.invoke(stu1));
setName.invoke(stu2, "影");
setAge.invoke(stu2, 25);
setAddress.invoke(stu2, "稻妻");
System.out.println(getName.invoke(stu2) + " " + getAge.invoke(stu2) + " " + getAddress.invoke(stu2));
}
}
测试结果: