欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于反射与内省

程序员文章站 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);
}
相关标签: java 反射 class