1、概念:
将类的各个组成部分封装为其他对象,这就是反射机制
好处:
1.可以在程序运行过程中,操作这些对象
2.可以解耦,提高程序的可扩展性
2、语法:
2.1 获取Class对象
第一种:
Class<类> Class对象名 = 类名.class;
第二种:
对象.getClass() getClass()方法在Object类中定义
第三种:
Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
2.2 获取成员变量
Field[] getFields(); // 获取所有的public修饰的成员变量
Field getField(String name); // 获取指定名字的public修饰的成员变量
Field[] getDeclaredFields(); // 获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name); //获取指定名字的所有的成员变量,不考虑修饰符
2.3 Field:成员变量
忽略访问权限修饰符的安全检查
Field对象.setAccessible(true); // 暴力反射
void set(Object obj, Object value); // 设置值,obj对象,value成员变量值
Object get(Object obj);获取值
2.4 获取构造方法
Constructor<?>[] getConstructors(); // 获取所有的public修饰的构造方法
Constructor getConstructors(类<?>… parameterTypes);
Constructor getDeclaredConstructor(类<?>… parameterTypes);
Constructor<?>[] getDeclaredConstrustor(); // 获取所有的构造方法,不考虑修饰符
2.5 Constructor:构造方法
创建对象:T newInstance(Object… initargs)
如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
忽略访问权限修饰符的安全检查
Constructor对象.setAccessible(true); // 暴力反射
2.6 获取成员方法
Method[] getMethods();
Method getMethod(String name, 类<?>… parameterTypes);
Method[] getDeclaredMethods();
Method getDeclaredMethod(String name, 类<?>… ParameterTypes);
2.7 Method:成员方法
执行成员方法:Object invoke(Object obj, Object…args);
忽略访问权限修饰符的安全检查
Method对象.setAccessible(true); // 暴力反射
获取方法名称:String getName();
2.8 获取类名
String getName();
public static void main(String[] args) throws Exception {
// 获取Person的Class对象
Class<Person> personClass = Person.class;
// Field[] getFields(); 获取所有的public修饰的成员变量
Field[] field = personClass.getFields();
for (Field field1 : field) {
System.out.println(field1);
}
// Field getField(String name); 获取指定名字的public修饰的成员变量
Field name = personClass.getField("a");
System.out.println(name);
// 根据获取到的Field对象设置和获取成员变量
Person p = new Person();
name.set(p, "张三");
Object o = name.get(p);
System.out.println(o);
// Field[] getDeclaredFields(); 获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
// 获取指定名字的所有的成员变量,不考虑修饰符
Field age = personClass.getDeclaredField("age");
System.out.println(age);
// 忽略访问权限修饰符的安全检查
age.setAccessible(true);
// 设置和获取成员变量b的值
age.set(p, 10);
System.out.println(age.get(p));
// 获取所有的public修饰的构造方法
Constructor<?>[] constructors = personClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
// 获取所有的构造方法,不考虑修饰符
Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
// 获取指定参数类型的构造方法,不考虑修饰符
Constructor<Person> declaredConstructors1 = personClass.getDeclaredConstructor(int.class);
System.out.println(declaredConstructors1);
// 获取指定参数类型的public修饰的构造方法
Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
System.out.println(constructor);
// 创建对象
Person person = constructor.newInstance("张三", 10);
System.out.println(person);
// 使用空参构造方法创建对象
Person person1 = personClass.newInstance();
System.out.println(person1);
// 获取成员方法
// 获取所有的public修饰的成员方法
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
// 获取所有的成员方法,不考虑修饰符
Method[] declaredMethods = personClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
// 获取指定名称及参数列表的public修饰的成员方法
Method method = personClass.getMethod("method", String.class);
System.out.println(method);
// 执行方法
method.invoke(p, "张三");
// 获取方法名称
String name1 = method.getName();
System.out.println(name1);
// 获取类名
String name2 = personClass.getName();
System.out.println(name2);
}
案例:
public static void main(String[] args) throws Exception {
// 不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法
// 1. 加载配置文件
// 1.1 创建Properties对象
Properties pro = new Properties();
// 1.2 加载配置文件,转换为集合
// 1,2,1 获取class目录下的配置文件
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
pro.load(is);
// 2. 获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
// 3. 加载该类进内存
Class cls = Class.forName(className);
// 4. 创建对象
Object o = cls.newInstance();
// 5. 获取方法对象
Method method = cls.getMethod(methodName);
// 6. 执行方法
method.invoke(o);
}