本文首发于本博客 猫叔的博客,转载请申明出处
前言
感谢GY丶L粉丝的提问:属性描述器PropertyDescriptor是干嘛用的?
本来我也没有仔细了解过描述符这一块的知识,不过粉丝问了,我就抽周末的时间看看,顺便学习一下,粉丝问的刚好是PropertyDescriptor这个属性描述符,我看了下源码。
1 | 复制代码/** |
emmmm,假装自己英语能厉害的说,属性描述符描述了一个属性,即Java Bean 通过一对访问器方法来导出。(没错,他确实是存在于java.beans包下的)
通过类关系图,可以知道,我们应该提前了解一下FeatureDescriptor才行了。很好,起码目前还没有设计抽象类或者接口。
FeatureDescriptor
1 | 复制代码/** |
okay,这是很合理的设计方式,FeatureDescriptor为类似PropertyDescriptor、EvebtSetDescriptor、MethodDescriptor的描述符提供了一些共用的常量信息。同时它也提供一个扩展功能,方便任意属性或键值对可以于设计功能相关联。
这里简单的说下,在我大致看了一下源码后(可能不够详细,最近有点忙,时间较赶),FeatureDescriptor主要是针对一下属性的一些get/set,同时这些属性都是基本通用于PropertyDescriptor、EvebtSetDescriptor、MethodDescriptor。
1 | 复制代码 private boolean expert; // 专有 |
其实该类还有另外几个方法,比如深奥的构造函数等等,这里就不深入探讨了。
PropertyDescriptor
那么我们大致知道了FeatureDescriptor,接下来就可以来深入了解看看这个属性描述符PropertyDescriptor
。
说到属性,大家一定会想到的就是get/set这个些基础的东西,当我打开PropertyDescriptor
源码的时候,我也看到了一开始猜想的点。
1 | 复制代码 private final MethodRef readMethodRef = new MethodRef(); |
这里的代码是我从源码中抽离的一部分,起码我们这样看可以大致理解,是分为写和读的步骤,那么就和我们初学java的get/set是一致的。
同时我还看到了,这个,及其注释。
1 | 复制代码 // The base name of the method name which will be prefixed with the |
这好像可以解释,为什么我们的属性在生成get/set的时候,第一个字母变成大写?!注释好像确实是这样写的。
由于可能需要一个Bean对象,所以我以前在案例中先创建了一个Cat
类。
1 | 复制代码public class Cat { |
构造函数
起码目前,我还不知道我应该怎么使用它,那么我们就一步一步来吧,我看到它有好几个构造函数,这是一个有趣而且有难度的事情,我们先试着创建一个PropertyDescriptor
吧。
- 第一种构造函数
1 | 复制代码 /** |
这个好像是参数最少的,它只需要我们传入一个属性字符串,还有对应的类就好了,其实它也是调用了另一个构造函数,只是它会帮我们默认生成读方法和写方法。方法中的Introspector.IS_PREFIX + NameGenerator.capitalize(propertyName)
其实就是自己拼出一个默认的get/set方法,大家有兴趣可以去看看源码。
那么对应的实现内容,我想大家应该都想到了。
1 | 复制代码 public static void main(String[] args) throws Exception { |
- 第二种构造函数
1 | 复制代码/** |
没错,这个构造函数就是第一种构造函数内部二次调用的,所需要的参数很简单,同时我也希望大家可以借鉴这个方法中的一些检测方式。这次的实现方式也是同样的形式。
1 | 复制代码 public static void main(String[] args) throws Exception { |
- 第三种构造函数
1 | 复制代码 /** |
这个不用传类,因为你需要传递两个实际的方法进来,所以主要三个对应属性的参数既可。看看大致的实现内容
1 | 复制代码 public static void main(String[] args) throws Exception { |
好了,大致介绍了几种构造函数与实现方式,起码我们现在知道它需要什么。
一些使用方式
其实在我上面写一些构造函数的时候,我想大家应该已经感受到与反射相关了,起码我感觉上是这样的,所以我一开始想到这样的案例形式,通过反射与这个属性描述类去赋予我的类。
1 | 复制代码 public static void main(String[] args) throws Exception { |
运行结果还是顺利的。
Cat{name=’river’, describe=’null’, age=0, weight=0}
可以看到,我们确实得到了一个理想中的对象。
那么我是不是可以改变一个已经创建的对象呢?
1 | 复制代码 public static void main(String[] args) throws Exception { |
上面的demo是,我先创建了一个对象,然后通过属性描述符读取name值,再进行修改值,最后输出的对象的值也确实改变了。
默认:river
修改后:Cat{name=’copy’, describe=’黑猫’, age=2, weight=4}
收尾
这是一个有趣的API,我想另外两个(EvebtSetDescriptor、MethodDescriptor)应该也差不多,大家可以再通过此方法去探究,只有自己尝试一次才能学到这里面的一些东西,还有一些项目场景的使用方式,不过一般的业务场景应该很少使用到这个API。那么这个东西究竟可以干什么呢?我想你试着敲一次也许有一些答案了。
公众号:Java猫说
现架构设计(码农)兼创业技术顾问,不羁平庸,热爱开源,杂谈程序人生与不定期干货。
本文转载自: 掘金