JAVA 反射机制
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意属性和方法;
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
反射可以无视修饰符,比如本来Private的变量或者方法,利用反射都可以调用
反射的代码不是死的,比较灵活,只需要修改配置文件就可以了
public static void main(String[] args) throws IOException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException { //获取系统类加载器,加载prop.properties文件 InputStream is =ClassLoader.getSystemClassLoader().getResourceAsStream("prop.properties"); //创建properties集合 Properties prop =new Properties(); //将文件中的数据读取到集合当中 prop.load(is); assert is != null; is.close(); //获取字节码文件的对象 Class clazz =Class.forName(prop.getProperty("className")); //获取构造器对象 Constructor constructor =clazz.getConstructor(); //利用构造器对象去创建一个对象 Object o =constructor.newInstance(); //获取方法对象 Method method =clazz.getMethod(prop.getProperty("methodName")); //运行方法 method.invoke(o); }
获取class对象的三种方式
1Class.forName(“全类名”);
2类名.class
3对象.getClass(); //getClass() 方法定义在Object类中
打印class对象得到的是该类的字节码文件
获取构造方法constructor对象并创建对象
Class类中用于获取构造方法的方法
1.Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
2.Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
3.Constructor<T> getConstructor(Class<?>... parameterTypes):返回单个公共构造方法对象
举例:
Class clazz =Class.forName("com.test.student")
Constructor constructor1=clazz.getConstructor(String.class,int.class) //里面的参数方对应构造方法参数的字节码文件
4.Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造方法对象
Constructor类中用于创建对象的方法
T newInstance(Object... initargs):根据指定的构造方法创建对象
setAccessible(boolean flag):设置为true,表示取消访问检查
利用newInstance()创建Student的对象
Student student = (Student) constructor.newInstance("zhangsan",22);
//在class类中,有一个newInstance 方法,可以利用空参直接创建一个对象
Student student =(Student) clazz.newInstance(); //但是这个方法已经过时了
获取私有化的对象: 也称为暴力反射
//先获取私有构造方法
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//被private修饰的成员,不能直接使用。如果反射强行获取并使用,需要临时取消访问检查
constructor.setAccessible(true);
//然后创建对象
Student student =(Student) constructor.newInstance("zhangsan");
反射获取成员变量并使用
第一步:获得class对象
第二步:获得Field对象
Class类中获得Field对象的方法:
1Field[] getFields():返回所有公共成员变量对象的数组
2Field[] getDeclaredFields():返回所有成员变量对象的数组
3Field getField(String name):返回单个公共成员变量对象
4Field getDeclaredField(String name):返回单个成员变量对象
第三步:赋值或者获取值
Field对象方法:
void set(Object obj, Object value):赋值
Object get(Object obj) 获取值。
Field field =clazz.getDeclaredField("money");
//被private修饰的成员,不能直接使用。如果反射强行获取并使用,需要临时取消访问检查
field.setAccessible(true);
前提都是先创建Student对象 再用Field对象调用方法
反射获取成员方法并运行
第一步:获取Class对象
第二步:获取Method对象
获取Method对象方法:
Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes) :返回单个公共成员方法对象
第二个参数放对应方法参数的类型的字节码文件
Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象
第三部:运行方法
Object invoke(Object obj, Object... args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
//创建class对象 Class clazz =Class.forName("com.object.Student"); //用class对象获取方法 Method method = clazz.getDeclaredMethod("study",String.class); //创建一个Student对象,当做方法的调用者 Student student =(Student) clazz.newInstance(); //运行并接收返回值 Object result =method.invoke(student,"语文书"); //打印返回值 System.out.println(result);