目录
一、什么是反射机制
- 1.将类的各个组成部分封装为其他对象
二、反射的优点
- 1.可以在程序运行的过程中操作对象
- 2.可以解耦,提高程序的可扩展性
三、获取Class对象的方式
说明: 同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个
3.1 Class.forName(全类名)
- 1.将字节码文件加载进内存,返回Class对象
- 2.多用于配置文件,将类名定义在配置文件中,读取文件,加载类
3.2 通过类名的class属性
- 1. 类名.class
- 2. 多用于参数的传递
3.3 对象.getClass()
- 1. getClass()方法在Object类中定义的
- 2. 多用于对象的获取字节码的方式
四、Class对象功能
4.1 获取功能
- 1.获取成员变量
// 获取所有公开的成员变量,包括继承变量
Field[] fields = clazz.getFields();
// 获取本类定义的成员变量,包括私有,但不包括继承的变量
Field[] declaredFields = clazz.getDeclaredFields();
// 获取指定变量
Field field = clazz.getField("name");
Field declaredField = clazz.getDeclaredField("name");
- 2.获取构造方法
//获取公开的构造方法
Constructor<?> constructor = clazz.getConstructor(String.class);
//获取所有的公开的构造方法
Constructor<?>[] constructors = clazz.getConstructors();
//获取所有的构造方法,包括私有
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(int.class, String.class);
- 3.获取成员方法
//获取所有可见的方法,包括继承的方法
Method[] methods = clazz.getMethods();
//获取本类定义的的方法
Method test = clazz.getMethod("test", String.class);
//获取本类定义的的方法,包括私有,不包括继承的方法
Method[] declaredMethods = clazz.getDeclaredMethods();
Method method = clazz.getDeclaredMethod("test", int.class, String.class);
4.2 Field成员变量
- 1.设置值
void set(Object obj, Object value);
- 2.获取值
get(Object obj);
Student student = new Student();
student.setName("张三");
Field nameField = Student.class.getDeclaredField("name");
nameField.setAccessible(true);
String name = (String)nameField.get(student);
System.out.println(name);
- 3.忽略访问权限修饰符的安全检查
// 暴力反射
setAccessible(true);
- 4.示例
// 反射调用成员变量
// 获取变量
Field age = clazz.getDeclaredField("age");
// 使私有成员允许访问
age.setAccessible(true);
// 为指定实例的变量赋值,静态变量,第一参数给null
age.set(o,22);
// 访问指定实例变量的值,静态变量,第一参数给null
age.get(o);
@Data
class Student{
private String name;
}
4.3 Constructor构造方法
- 1.创建对象
T newInstance(Object ...initargs)
- 2.如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
//执行无参构造创建对象
Object o = clazz.newInstance();
//执行有参构造创建对象
clazz.newInstance();
clazz.getConstructor(int.class,String.class);//获取构造方法
4.4 Method方法对象
- 1.执行方法
Object invoke(Object obj,Object... args)
- 2.获取方法名称
String getName获取方法名
- 3.示例
// 反射调用成员方法
Method m = clazz.getDeclaredMethod("test",String.class);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(o, "你好");//让指定实例来执行该方法
五、示例
package learning.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @Author wangyouhui
* @Description 反射
*/
public class ReflectTest {
private String name;
private int age;
public ReflectTest(int age, String name){
this.name = name;
this.age = age;
}
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("learning.reflect.ReflectTest");
//获取包名
String packageName = clazz.getPackage().getName();
//获取类名
String simpleName = clazz.getSimpleName();
//获取完整类名
String name = clazz.getName();
//获取成员变量定义信息
// 获取所有公开的成员变量,包括继承变量
Field[] fields = clazz.getFields();
// 获取本类定义的成员变量,包括私有,但不包括继承的变量
Field[] declaredFields = clazz.getDeclaredFields();
Field field = clazz.getField("name");
Field declaredField = clazz.getDeclaredField("name");
//获取构造方法定义信息
//获取公开的构造方法
Constructor<?> constructor = clazz.getConstructor(String.class);
//获取所有的公开的构造方法
Constructor<?>[] constructors = clazz.getConstructors();
//获取所有的构造方法,包括私有
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(int.class, String.class);
//获取方法定义信息
//获取所有可见的方法,包括继承的方法
Method[] methods = clazz.getMethods();
//获取本类定义的的方法
Method test = clazz.getMethod("test", String.class);
//获取本类定义的的方法,包括私有,不包括继承的方法
Method[] declaredMethods = clazz.getDeclaredMethods();
Method method = clazz.getDeclaredMethod("test", int.class, String.class);
//反射新建实例
//执行无参构造创建对象
Object o = clazz.newInstance();
//执行有参构造创建对象
clazz.newInstance();
clazz.getConstructor(int.class,String.class);//获取构造方法
// 反射调用成员变量
// 获取变量
Field age = clazz.getDeclaredField("age");
// 使私有成员允许访问
age.setAccessible(true);
// 为指定实例的变量赋值,静态变量,第一参数给null
age.set(o,22);
// 访问指定实例变量的值,静态变量,第一参数给null
age.get(o);
// 反射调用成员方法
Method m = clazz.getDeclaredMethod("test",String.class);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(o, "你好");//让指定实例来执行该方法
}
}