反射
反射允许对成员变量、成员方法和构造方法的信息进行编程访问。
需要从class文件中获取
获取class对象的三种方式
①Class.forName("全类名")——源码阶段(编写java文件,生成class字节码文件)
最常用的一种方式
②类名.class——加载阶段(加载进内存)
一般是当做参数使用
③对象.getClass()——运行阶段
已经有了这个类的对象时才能使用
利用反射获取狗造方法
Class类中用于获取构造方法的方法
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor<T> getConstructor(Class<?>...parameterTypes) | 返回单个公共构造方法对象 |
Constructor<T>getDeclaredConstructor(Class<>...papameterTypes) | 返回单个构造方法对象 |
Constructor类中用于创建对象的方法
T newInstance(Object... initargs) | 利用获取到的构造对象创建类对象 |
setAccessible(boolean flag) | 临时取消权限校验(比如private) |
利用反射获取成员变量
class类中用于获取成员变量的方法
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
Field类中用于创建对象的方法
void set(Object obj,Object value) | 赋值 |
Object get(Object obj) | 获取值 |
利用反射获取成员方法
Class类中用于获取成员方法的方法
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name,Class<?>... parameterTypes) | 返回单个公共成员方法对象 |
MethodgetDeclaredMethod(String name,Class<?>... parameterTypes) | 返回单个成员方法对象 |
Method类中用于创建对象的方法
Object invoke(Object obj,Object... args) | 运行方法 参数一:用obj对象调用该方法 参数二:调用方法传递的参数(没有就不写) 返回值:方法的返回值,如果没有就不写 |
反射的作用
①获取一个类里所有的信息,获取到之后,再执行其他业务逻辑
②结合配置文件,动态的创建对象并调用方法
练习
对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中
package com.heima.a03test;
import java.io.*;
import java.lang.reflect.Field;
public class ReflectDemo {
public static void main(String[] args) throws IllegalAccessException, IOException {
/*
对于任意一个对象,都可以把对象中的所有字段名和值,保存到文件中
*/
Student s = new Student("小艺",23,'女',169,"睡觉");
Teacher t = new Teacher("张老师",30000);
saveObject(s);
}
/**
* 把对象中的所有成员变量名和值保存到本地文件中
* @param obj
*/
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
//1.先获取字节码文件
Class<?> clazz = obj.getClass();
//2.通过字节码文件获取成员变量
Field[] fields = clazz.getDeclaredFields();
BufferedWriter bw = new BufferedWriter(new FileWriter("myreflect\\a.txt"));
for (Field field : fields) {
//不确定获取到的变量是否是有权限的,所有使用setAccessible临时解除权限
field.setAccessible(true);
//获取成员变量的名字
String name = field.getName();
//获取值
Object value = field.get(obj);
// System.out.println(name+"="+value);
//将获取的数据写到本地文件
bw.write(name+"="+value);
bw.newLine();//换行
}
bw.close();
}
}
反射可以和配置文件结合的方式,动态的创建对象,并调用方法
package com.heima.a04test;
import com.sun.xml.internal.fastinfoset.tools.FI_DOM_Or_XML_DOM_SAX_SAXEvent;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
/*
反射可以和配置文件结合的方式,动态的创建对象,并调用方法
*/
//1.读取配置文件
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("myreflect\\prop.properties");
prop.load(fis);
fis.close();
System.out.println(prop);
//2.获取全类名和方法名
String className = (String) prop.get("className");
String methodName = (String) prop.get("method");
//3.利用反射创建对象,并执行方法
Class clazz = Class.forName(className);
Constructor con = clazz.getDeclaredConstructor();
Student stu = (Student) con.newInstance();
//4.成员方法并运行
Method method = clazz.getDeclaredMethod(methodName);
method.setAccessible(true);
method.invoke(stu);
}
}