关于反射与内省
程序员文章站
2024-01-20 15:40:46
...
@反射和内省
反射
在程序运行过程中,通过字节码对象,去获取类中的成员信息(构造器,方法,字段)
为什么使用反射:可以通过一个对象,获取到它的真实类型以及调用该对象中的方法
获取字节码对象的方式
// 通过Class类的forName(String className)方法来获取字节码对象 className:类的全限定名
Class clz = Class.forName("cn.wolfcode._01_reflect.Person");
// 通过对象的getClass()方法来获取字节码对象
Class clz2 = new Person().getClass();
// 通过基本类型的class字段来获取字节码对象
Class clz3 = Person.class;
通过字节码对象去获取构造器以及调用构造器
// 获取字节码对象
Class clz = Class.forName("cn.wolfcode._01_reflect.Person");
// 获取所有的public 构造器
Constructor[] cons1 = clz.getConstructors();
// 获取所有的构造器 包括 private
Constructor[] cons2 = clz.getDeclaredConstructors();
// 获取无参构造器
Constructor con1 = clz.getConstructor();
Object obj1 = con1.newInstance();
// 获取带参构造器
Constructor con2 = clz.getConstructor(String.class, int.class);
Object obj2 = con2.newInstance("小狼", 18);
// 获取指定的 private 构造器
Constructor con3 = clz.getDeclaredConstructor(String.class);
con3.setAccessible(true);
Object obj3 = con3.newInstance("小马");
// 创建对象的快捷方式 调用无参构造器
Object obj = clz.newInstance();
方法的获取和调用
Class clz = Class.forName("cn.wolfcode._01_reflect.Person");
Object obj = clz.newInstance();
// 获取所有的 public 方法 包括父类的
Method[] methods = clz.getMethods();
// 获取所有的方法 包括 private 不包括父类的
Method[] methods2 = clz.getDeclaredMethods();
// 获取指定参数的 public 方法 包括父类的
Method sayHelloMethod = clz.getMethod("sayHello", String.class);
// 获取指定参数的 private 方法 不包括父类的
Method doWorkMethod = clz.getDeclaredMethod("doWork", String.class);
// 设置可访问
doWorkMethod.setAccessible(true);
// 调用私有的方法
doWorkMethod.invoke(obj, "小狼");
// 调用静态方法
Method staticSayHelloMethod = clz.getDeclaredMethod("sayHello", String.class, int.class);
// 不需要对象去调用 但是参数必须加上null,不然会把后面的参数作为调用方法的对象
staticSayHelloMethod.invoke(null, "小马", 18);
字段的获取和操作
Class clz = Class.forName("cn.wolfcode._01_reflect.Person");
Object obj = clz.newInstance();
// 获取所有 public 字段
Field[] fields = clz.getFields();
// 获取所有的字段 包括private
Field[] fields2 = clz.getDeclaredFields();
// 获取单个字段 private
Field nameField = clz.getDeclaredField("name");
// 设置私有字段可访问
nameField.setAccessible(true);
// 操作 name 字段
// 设置 name 字段的数据
nameField.set(obj, "小狼");
// 获取 name 字段的数据
Object nameValue = nameField.get(obj);
复习JavaBean规范
1.使用 public 修饰
2.字段私有化
3.提供getter/setter方法
4.公共无参构造器
JavaBean属性是通过getter/setter方法推导出来的
内省
操作JavaBean中的属性
作用:
1.获取到属性名和属性类型等相关状态信息
2.获取属性对应的读写方法操作属性的值等操作方式
内省常用的API
// 创建对象来调用方法
Person obj = Class.forName("cn.wolfcode._01_reflect.Person").newInstance();
// 把JavaBean 转化成 beanInfo
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class, Object.class);
// 通过beanInfo 获取所有的属性
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
// 遍历属性描述器数组,获取到每个属性描述器
for(PropertyDescriptor pd : pds) {
// 获取属性名
pd.getName();
// 获取属性类型
pd.getPropertyType();
// 获取属性的 setter/getter 方法
Method getMethod = pd.getReadMethod();
Method setMethod = pd.getWriteMethod();
// 调用name属性的setter方法
if ("name".equals(pd.getName())) {
setMethod.invoke(obj, "小马");
}
//调用getter方法
getMethod.invoke(obj);
}
上一篇: CI框架整合widget(页面格局)的方法_php实例
下一篇: 设计模式-结构型软件设计模式(三)