定义
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。
为什么要有反射呢?
- 反射让开发人员可以通过外部类的全路径名创建对象,并使用这些类,实现一些扩展的功能。
- 反射让开发人员可以枚举出类的全部成员,包括构造函数、属性、方法。以帮助开发者写出正确的代码。
- 测试时可以利用反射 API 访问类的私有成员,以保证测试代码覆盖率。
举例子:
1.当我们的程序在运行时,需要动态的加载一些类这些类开始不用加载到jvm,而是在运行时根据需要才加载,举个例子我们的项目底层有时是用mysql,有时用oracle,需要动态地根据实际情况加载驱动类,这个时候反射就有用了,假设 com.java.driver.myqlConnection,com.java.driver.oracleConnection这两个类我们要用,这时候我们的程序就写得比较动态化,通过Class tc = Class.forName(“com.java.dbtest.TestConnection”);通过类的全类名让jvm在服务器中找到并加载这个类,
2.spring,会发现当你配置各种各样的bean时,是以配置文件的形式配置的,配置需要的bean,spring容器就会根据需求去动态加载.
3.在JBDC里也有反射获取加载类,账号,密码
使用
- 反射获取 Class 类 (Class)
- 反射获取类中的所有字段 (Field)
- 反射获取类中的所有构造方法(Constructor)
- 反射获取类中的方法 (Method)
Field 类:提供有关类的属性信息,以及对它的动态访问权限。它是一个封装反射类的属性的类。
Constructor 类:提供有关类的构造方法的信息,以及对它的动态访问权限。它是一个封装反射类的构造方法的类。
Method 类:提供关于类的方法的信息,包括抽象方法。它是用来封装反射类方法的一个类。
Class 类:正在运行的 Java 应用程序中的类的实例。
实践
首先写一个类
package reflection;
/**
* 测试类
*/
public class TestR {
//私有属性name
private String name;
//公共属性password
public String password;
//构造方法
public TestR() {
}
//有参构造方法
public TestR(String name, String password) {
this.name = name;
this.password = password;
}
public void setName(String name) {
this.name = name;
}
public String test(String val){
System.out.println(val +" name:"+name+" password:"+password);
return "test";
}
}
反射应用
//通过包路径获取 TestClass
Class testClass = Class.forName("com.test.reflection.TestR");
Class testClass1 = TestR.class;
//获取字段属性
// 1.获取所有声明的字段属性
Field[] declaredFieldList = testClass.getDeclaredFields();
for (Field declaredField : declaredFieldList) {
System.out.println("declared Field: " + declaredField);
}
// 2.获取所有公有的字段属性
Field[] fieldList = testClass.getFields();
for (Field field : fieldList) {
System.out.println(" public field: " + field);
}
//构造方法
// 3.获取所有声明的构造方法
Constructor[] declaredConstructorList = testClass.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructorList) {
System.out.println("testClass declared Constructor: " + declaredConstructor);
}
// 4.获取所有公有的构造方法
Constructor[] constructorList = testClass.getConstructors();
for (Constructor constructor : constructorList) {
System.out.println("testClass constructor: " + constructor);
}
//方法
// 1.获取所有声明的函数
Method[] declaredMethodList = testClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethodList) {
System.out.println("declared Method: " + declaredMethod);
}
// 2.获取所有公有的函数
Method[] methodList = testClass.getMethods();
for (Method method : methodList) {
System.out.println("method: " + method);
}
Constructor testConstructor = testClass.getDeclaredConstructor(String.class);
// 如果私有的函数,需要设置accessible true
testConstructor.setAccessible(true);
// 使用构造方法的newInstance方法创建对象,传入构造方法所需参数,如果有多个参数,用','连接即可
Object test = testConstructor.newInstance("pengzc","123");
Field testPasswordField = testClass.getDeclaredField("password");
// 使用字段的set方法设置字段值,传入此对象以及参数值
testPasswordField.set(test,"456");
// 4.获取声明的函数,传入所需参数的类名,如果有多个参数,用','连接即可
Method studentShowMethod = testClass.getDeclaredMethod("show",String.class);
// 如果私有的函数,需要设置accessible true
studentShowMethod.setAccessible(true);
// 使用函数的invoke方法调用此函数,传入此对象以及函数所需参数,如果有多个参数,用','连接即可。函数会返回一个Object对象,使用强制类型转换转成实际类型即可
Object result = studentShowMethod.invoke(test,"test哈哈哈哈");
System.out.println("result: " + result);