Java内省(Introspector)理解

本文详细介绍了Java内省机制的基本概念及其应用场景,并提供了基于内省机制进行JavaBean属性操作的具体实例,包括直接调用getter/setter方法及使用BeanUtils工具包简化操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内省(Introspector) 是Java语言对JavaBean类属性、事件的一种缺省处理方法。

JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。如果在两个模块之间传递信息,可以将信息封装进JavaBean中,这种对象称为“值对象”(Value Object/VO)。这些信息储存在类的私有变量中,通过set()、get()来访问类中的属性。

以下是一个标准的JavaBean:

public class Person {
    private String name;

    private int age;

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

在Person类中有属name,age属性, 我们可以通setName()、getName()方法来得到其值或者设置新的值。通过 setName/getName来访问 userName属性,这就是默认的规则。 Java JDK中提供了一套 API 用来访问某个属性的 getter/setter 方法,这就是内省。

JDK中内省的相关类库:

PropertyDescriptor类:
  PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:
      1. getPropertyType(),获得属性的Class对象;
      2. getReadMethod(),获得用于读取属性值的方法;getWriteMethod(),获得用于写入属性值的方法;
      3. hashCode(),获取对象的哈希值;
      4. setReadMethod(Method readMethod),设置用于读取属性值的方法;

      5. setWriteMethod(Method writeMethod),设置用于写入属性值的方法。

使用Java内省操作JavaBean,这是没有任何问题的。但是随之而来的就是编码的复杂度,因此很多第三方类库封装了JavaBean的内省操作,典型的工具包有:BeanUtils工具包(下载地址:http://commons.apache.org/beanutils/)

demo测试代码如下:

public class Person {
    private String name;

    private int age;

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static void main(String[] args) throws Exception {
        try {
            PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(Person.class).getPropertyDescriptors();
            for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                System.out.printf("属性名:%s%n", propertyDescriptor.getName());
                System.out.printf("属性类型:%s%n", propertyDescriptor.getPropertyType());
                System.out.printf("属性读方法:%s%n", propertyDescriptor.getReadMethod());
                System.out.printf("属性写方法:%s%n", propertyDescriptor.getWriteMethod());
            }
            //测试setProperty()、getProperty()两个方法
            testProperty();
            //测试setPropertyByIntrospector()、getPropertyByIntrospector()两个方法
            testByIntrospector();
            //测试BeanUtils工具包
            testBeanUtils();
        } catch (IntrospectionException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置bean的某个属性值
     * @param obj
     * @param propertyName
     * @param value
     * @throws Exception
     */
    private static void setProperty(Object obj,String propertyName,Object value)throws Exception {
        // 获取bean的某个属性的描述符  两种方式
        PropertyDescriptor pd = new PropertyDescriptor(propertyName,obj.getClass());
        // 获得用于写入属性值的方法
        Method setMethod = pd.getWriteMethod();
        System.out.printf("写入方法的方法名:%s%n", setMethod.getName());
        // 写入属性值
        setMethod.invoke(obj, value);
    }

    /**
     * 获取bean的某个属性值
     * @param obj
     * @param propertyName
     * @return
     * @throws Exception
     */
    private static Object getProperty(Object obj,String propertyName) throws Exception {
        // 获取Bean的某个属性的描述符  两种方式
        PropertyDescriptor pd = new PropertyDescriptor(propertyName,obj.getClass());
        // 获得用于读取属性值的方法
        Method getMethod = pd.getReadMethod();
        System.out.printf("读取方法的方法名:%s%n", getMethod.getName());
        // 读取属性值
        return getMethod.invoke(obj);
    }

    /**
     * 通过内省设置bean的某个属性值
     * @param obj
     * @param propertyName
     * @param value
     * @throws Exception
     */
    public static void setPropertyByIntrospector(Object obj, String propertyName, Object value) throws Exception {
        // 获取bean信息
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        // 获取bean的所有属性列表
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        // 遍历属性列表,查找指定的属性
        if (propertyDescriptors != null && propertyDescriptors.length > 0) {
            for (PropertyDescriptor propDesc : propertyDescriptors) {
                // 找到则写入属性值
                if (propDesc.getName().equals(propertyName)) {
                    Method methodSetUserName = propDesc.getWriteMethod();
                    System.out.printf("写入方法的方法名:%s%n", methodSetUserName.getName());
                    // 写入属性值
                    methodSetUserName.invoke(obj, value);
                    break;
                }
            }
        }
    }

    /**
     * 通过内省获取bean的某个属性值
     * @param obj
     * @param propertyName
     * @throws Exception
     */
    public static Object getPropertyByIntrospector(Object obj, String propertyName) throws Exception {
        // 获取bean信息
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        // 获取bean的所有属性列表
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        if (propertyDescriptors != null && propertyDescriptors.length > 0) {
            for (PropertyDescriptor propDesc : propertyDescriptors) {
                // 找到则读取属性值
                if (propDesc.getName().equals(propertyName)) {
                    Method methodGetUserName = propDesc.getReadMethod();
                    System.out.printf("读取方法的方法名:%s%n", methodGetUserName.getName());
                    // 读取属性值
                    Object objUserName = methodGetUserName.invoke(obj);
                    return objUserName;
                }
            }
        }
        return null;
    }

    /**
     * 测试setProperty()、getProperty()两个方法
     * @throws Exception
     */
    public static void testProperty() throws Exception {
        System.out.println("------------------------------华丽的分割线------------------------------");
        Person person = new Person();
        String propertyName = "name";
        Object nameValue = getProperty(person,propertyName);
        System.out.printf("属性name的值=%s%n", nameValue);
        Object name = "张三";
        setProperty(person, propertyName, name);
        System.out.printf("get()获取属性name的值=%s%n", person.getName());
        System.out.printf("getProperty()获取属性name的值=%s%n", getProperty(person, propertyName));
    }

    /**
     * 测试setPropertyByIntrospector()、getPropertyByIntrospector()两个方法
     * @throws Exception
     */
    public static void testByIntrospector() throws Exception {
        System.out.println("------------------------------华丽的分割线------------------------------");
        Person personOther = new Person();
        String propertyAge = "age";
        Object ageValue = getPropertyByIntrospector(personOther,propertyAge);
        System.out.printf("属性age的值=%s%n", ageValue);
        Object age = 20;
        setPropertyByIntrospector(personOther, propertyAge, age);
        System.out.printf("get()获取属性age的值=%s%n", personOther.getAge());
        System.out.printf("getPropertyByIntrospector()获取属性age的值=%s%n", getPropertyByIntrospector(personOther, propertyAge));
    }

    /**
     * 内省操作非常的繁琐,所以所以Apache开发了一套简单、易用的API来操作Bean的属性——BeanUtils工具包。
     * 下载地址:http://commons.apache.org/beanutils/
     */
    public static void testBeanUtils() {
        System.out.println("------------------------------华丽的分割线------------------------------");
        Person person = new Person();
        try {
            BeanUtils.setProperty(person, "name", "王五");
            System.out.printf("name:%s%n", BeanUtils.getProperty(person, "name"));
            BeanUtils.setProperty(person, "age", 30);
            System.out.printf("age:%s%n", BeanUtils.getProperty(person, "age"));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}
内容概要:本文详细介绍了900W或1Kw,20V-90V 10A双管正激可调电源充电机的研发过程和技术细节。首先阐述了项目背景,强调了充电机在电动汽车和可再生能源领域的重要地位。接着深入探讨了硬件设计方面,包括PCB设计、磁性器件的选择及其对高功率因数的影响。随后介绍了软件实现,特别是程序代码中关键的保护功能如过流保护的具体实现方法。此外,文中还提到了充电机所具备的各种保护机制,如短路保护、欠压保护、电池反接保护、过流保护和过温度保护,确保设备的安全性和可靠性。通讯功能方面,支持RS232隔离通讯,采用自定义协议实现远程监控和控制。最后讨论了散热设计的重要性,以及为满足量产需求所做的准备工作,包括提供详细的PCB图、程序代码、BOM清单、磁性器件和散热片规格书等源文件。 适合人群:从事电力电子产品研发的技术人员,尤其是关注电动汽车充电解决方案的专业人士。 使用场景及目标:适用于需要高效、可靠充电解决方案的企业和个人开发者,旨在帮助他们快速理解和应用双管正激充电机的设计理念和技术要点,从而加速产品开发进程。 其他说明:本文不仅涵盖了理论知识,还包括具体的工程实践案例,对于想要深入了解充电机内部构造和工作原理的人来说是非常有价值的参考资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值