反射允许对封装类的字段,方法和构造函数的信息进行编程访问。(成员变量、成员方法、构造方法)
获取class对象:
获取的是class的字节码对象
Class.forName( "全类名"); 源代码阶段//全类名:包名加类名
类名.class 加载阶段
对象.getClass(); 运行阶段
Class class=Class.forName("");
Class class=Student.class;
Student s=new Student();
Class class=s.getClass();
获取构造方法:
Class clazz=Class.forName("");//Student 获取对象
//获取构造方法
Constructor[] cons=clazz.getConStructors();
for(Constructor con:cons){}
Constructor[] cons1=clazz.getDeclaredConstructors();//获取所有
Constructor cons2=clazz.getDeclaredConstructor();//返回单个。包括私有
//单个构造中可以传入参数来返回确定的构造方法,参数与构造方法保持一致
Constructor cons3=clazz.getDeclaredConstructor(String.class);//获取string的字节码文件
//获取构造方法后就可以获得构造方法的信息
int s=cons3.getModifiers();//权限修饰符 可以在api文档中查常量修饰符知道各个修饰符对应的数字
//利用获取的构造方法来创建对象
Student st=(Student)cons3.newInstance("张三");//此时创建的构造方法要和获取的一样
//但是如果如果是私有的是不可以直接创建的
//暴力反射,临时取消私有权限
cons3.setAccessible(true);
Student st=(Student)cons3.newInstance("张三");
获取成员变量:
Class clazz=Class.forName("Student");//Student:name age
Field[] fields=clazz.getFields();
Field name=clazz.getField("name");
//其他和获取构造方法差不多
String getType()获取成员变量类型
String getName()获取名字
变量名.get(对象)获取对象的该成员变量的值
变量名.set(对象,修改成的值)修改
获取成员方法:
getMethods 也会获取到父类中的方法
getDeclareMethods不会获取到父类中方法
获取单个方法传入参数是方法名和参数.class
//获取方法的形参
Parameter[] parameters=m.getParameters();
//获取方法抛出的异常
Class[] exceptionTypes=m.getExceptionTypes();
//调用方法
Student s;
m.invoke(对象,方法的参数);//若有返回值
String s=(String)m.invoke(对象,方法的参数);
动态代理:
特点:无侵入式的给代码增加额外的功能
eg:
Star为要实现的接口(实现类和代理都要实现这个接口)
main函数:
2中调用sing方法后底层会调用代理中的invoke方法
然后method对应sing,传入参数对应args,再去调用method.invoke,传入对象以及该对象本方法对应的参数