java 中的内省 introspector

概述

经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。

内省(IntroSpector)是Java语言对JavaBean 类属性、事件的一种处理方法。 例如类A中有属性name,那我们可以通过getName,setName 来得到其值或者设置新的值。 通过getName/setName 来访问name属性,这就是默认的规则。

Java中提供了一套API 用来访问某个属性的getter/setter方法,通过这些API可以使你不需要了解这个规则,这些API存放于包java.beans 中。

一般的做法是通过类Introspector的getBeanInfo方法获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。

我们又通常把javabean的实例对象称之为值对象,因为这些bean中通常只有一些信息字段和存储方法,没有功能性方法。

一个JavaBean类可以不当JavaBean用,而当成普通类用。JavaBean实际就是一种规范,当一个类满足这个规范,这个类就能被其它特定的类调用。一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。去掉set前缀,然后取剩余部分,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。

内省访问JavaBean有两种方法:

  1. 通过PropertyDescriptor来操作Bean对象
public static void demo1() throws Exception {
    User user = new User("zhangsan", 21);
    String propertyName = "name";
    // 直接指定要访问的属性
    PropertyDescriptor pd = new PropertyDescriptor(propertyName, user.getClass());
    // 获取到读方法
    Method readMethod = pd.getReadMethod();
    // 反射机制调用
    Object invoke = readMethod.invoke(user, null);
    System.out.println("名字:" + invoke);
    pd.getWriteMethod().invoke(user, "lisi");
    invoke = readMethod.invoke(user, null);
    System.out.println("名字:" + invoke);
    }
}
  1. 通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。
public static void demo2() throws Exception {
    // 获取整个Bean的信息
    // BeanInfo beanInfo= Introspector.getBeanInfo(user.getClass());
    // 在Object类时候停止检索,可以选择在任意一个父类停止
    BeanInfo beanInfo = Introspector.getBeanInfo(user.getClass(), Object.class);

    System.out.println("所有属性描述:");
    // 获取所有的属性描述
    PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
    for (PropertyDescriptor propertyDescriptor : pds) {
        System.out.println(propertyDescriptor.getName());
    }
    System.out.println("所有方法描述:");
    for (MethodDescriptor methodDescriptor : beanInfo.getMethodDescriptors()) {
        System.out.println(methodDescriptor.getName());
        // Method method = methodDescriptor.getMethod();
    }
}

User.java

public class User {
    private String name;
    private int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Linyb极客之路

Java中final和static关键字总结

final修饰的类不可被继承,例如java.lang.Math就是一个 final类,不可被继承。

1363
来自专栏软件开发 -- 分享 互助 成长

C++ 字符串分割

    java和C#中字符串都可以使用split进行分割,但是C++中却没有这个方法,之前总是自己写一个函数自己进行分割,倒也不麻烦,今天在网上找了类似的函数...

2446
来自专栏nnngu

如何用java语言实现C#中的ref关键字(按引用传递参数)的效果

在上一篇文章中(Java的参数传递是值传递还是引用传递),主要分析了java语言的参数传递只有按值传递而没有按引用传递。 先看一下微软的C#文档对按引用传递的定...

4676
来自专栏Esofar 开发日记

SQL Server常见数据类型介绍

1013
来自专栏技术之路

c++ 副本构造器

我们都知道两个指针指向同一个变量时如果一个指针被释放那么另一个就会出问题 为了说明问题我做了一个很恶心的小例子 class C { public : C...

2059
来自专栏IMWeb前端团队

ECMAScript 6 学习笔记

作用域不同 ES6中,let和const实际上为JavaScript新增了块级作用域,函数本身的作用域,在其所在的块级作用域之内。 let和const的用法 ...

2078
来自专栏用户2442861的专栏

python语法31[引用和拷贝]

  If an object’s value can be modified, the object is said to be mutable. If the...

811
来自专栏IT可乐

浅谈 Integer 类

  突然发现自己对Integer i = 10;这种语法不太明白,于是乎有了这篇文章,那么在讲解 Integer 之前,我们先看下面这段代码: public s...

2139
来自专栏机器学习算法与Python学习

Python:爬虫系列笔记(6) -- 正则化表达(推荐)

在前面我们已经搞定了怎样获取页面的内容,不过还差一步,这么多杂乱的代码夹杂文字我们怎样把它提取出来整理呢?下面就开始介绍一个十分强大的工具,正则表达式! 1.了...

3688

Python3 字符串操作

字符串是Python中最基本的数据类型之一,用于表示文本数据。几乎每个应用程序都涉及使用字符串,Python的str类提供了许多方法来简化字符串操作。

1344

扫码关注云+社区

领取腾讯云代金券