为什么 PropertyDescriptor return 是第一个字符为大写的 属性 名称?

Why does PropertyDescriptor return a property name with uppercase as first character?

我正在通过

获取有关 class 的信息
Introspector.getBeanInfo(this.getClass()).getPropertyDescriptors()

然后通过调用 propery[i].getName() 获取 属性 的名称。

如果 属性 没有单字母部分,一切都很好。例如,如果 属性 的名称为 personAddress(同时其名称为 getter/setter -> getPersonAddress()setPersonAddress(String personAddress)),就可以了,getName() returns personAddress.

但是如果 属性 有一个名字 rPersonId (getRPersonId(), setRPersonId(Long rPersonId)) 那么 getName() returns "RPersonId",即首字母大写!为什么?

据此:https://docs.oracle.com/javase/7/docs/api/java/beans/FeatureDescriptor.html:

public String getName()-> Gets the programmatic name of this feature.

那么,为什么它 return 的名字与其 getter 或 setter 的名字有某种关联,而不是 属性 的真名?

因为这是部分宗教。

使用 Java Beans 的人认为应该始终通过一对方法访问属性。所以你没有得到数据成员的名字。您将获得只能通过方法访问的 属性。

这是来自文档:

A PropertyDescriptor describes one property that a Java Bean exports 
via a pair of accessor methods.

https://docs.oracle.com/javase/7/docs/api/java/beans/PropertyDescriptor.html

理论是你永远不应该使用数据成员名称,所以通过 Bean 接口,他们不会给你那个。

这实际上是记录在案的行为。

首先,属性 名称完全是通过发现它们的 getter 和 setter 来定位的,而不是通过查看 class 的字段来定位的。这在 Java Beans specification:

的第 8.3 段中指定

If we discover a matching pair of get<PropertyName> and set<PropertyName> methods that take and return the same type, then we regard these methods as defining a read-write property whose name will be <propertyName>.

所以当你对包含Long getRPersonId()setRPersonId(Long)的class进行内省时,可以从中提取出属性。 属性 的名字一般是首字母小写,其余不变。但情况并非总是如此,确切的规则在第 8.8 段中:

Thus when we extract a property or event name from the middle of an existing Java name, we normally convert the first character to lower case. However to support the occasional use of all upper-case names, we check if the first two characters of the name are both upper case and if so leave it alone. So for example:

  • FooBah becomes fooBah
  • Z becomes z
  • URL becomes URL

We provide a method Introspector.decapitalize which implements this conversion rule.

在上面的示例中,getter 和 setter 将提供字符串 RPersonId 以转换为 属性 名称。由于前两个字符是大写的,所以第一个字符不会是小写的。因此,将导出的 属性 名称是 RPersonId,这解释了您的输出。

您还可以调用方法 decapitalize 来查看从一对 getter / setter:

中找到哪个 属性 名称
System.out.println(Introspector.decapitalize("RPersonId"));     // prints RPersonId
System.out.println(Introspector.decapitalize("PersonAddress")); // prints personAddress