5

我正在制作一个使用 Drools 规划器的应用程序。

@ValueRangeFromSolutionProperty应该引用另一个类的属性(在NQueens这种情况下)。来自@ValueRangeFromSolutionProperty 的JavaDocs

propertyName

    The property name of which exists a getter on the Solution that returns a Collection. 

但我注意到一个不一致的地方:注释器使用rowList来自NQueens. 但是rowList(相对于RowList)是一个私有变量(见下面的片段)。如果它应该通过自省来推断一个属性(从它的 getter 和 setter 方法),它不应该拼写RowList为 ingetRowList()吗?

问题: Java 如何从 getter 方法推断(内省)属性名称(大小写和全部)?

还是直接@ValueRangeFromSolutionProperty访问私有变量?


背景细节: From Queen.java,一个代表棋盘上皇后的类:

public class Queen extends AbstractPersistable {
....
@ValueRangeFromSolutionProperty(propertyName = "rowList")
public Row getRow() {
    return row;
....

From NQueens.java,从中@ValueRangeFromSolutionProperty获取其属性的类:

public class NQueens extends AbstractPersistable implements Solution<SimpleScore> {
...
private List<Column> columnList;
private List<Row> rowList;
....
public List<Row> getRowList() {
    return rowList;
...
4

3 回答 3

16

JavaBeans 规范说,对于一个属性,propertyName应该有一个 getter 方法getPropertyName()和/或一个 setter 方法setPropertyName()

属性由唯一存在的 getter 和 setter 方法定义,也可以是计算值。不需要对象上的实例变量。

该规范定义了属性和 getter/setter 方法的大小写规则:

因此,当我们从现有 Java 名称的中间提取属性或事件名称时,我们通常将第一个字符转换为小写。然而,为了支持偶尔使用所有大写名称,我们检查名称的前两个字符是否都是大写的,如果是,则不处理。例如,

“FooBah”变成“fooBah”,“Z”变成“z”,“URL”变成“URL”


该方法实际上实现为:

/*
Utility method to take a string and convert it to normal Java variable name 
capitalization. This normally means converting the first character from upper case to  
lower case, but in the (unusual) special case when there is more than one character  
and both the first and second characters are upper case, we leave it alone.

Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays as "URL".

 Parameters:
     name The string to be decapitalized.
 Returns:
 The decapitalized version of the string.
 */
 public static String  decapitalize(String name) {
 if (name == null || name.length() == 0) {
 return name;
 }
 if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                     Character.isUpperCase(name.charAt(0))){
        return name;
     }

     char chars[] = name.toCharArray();
     chars[0] = Character.toLowerCase(chars[0]);
     return new String(chars);
 }

所以:

  1. 如果name为空,则原样返回
  2. 如果name前两个字符大写,则原样返回
  3. 所有其他字符串,将第一个字符大写
于 2012-01-23T09:35:21.143 回答
3

这是由 JavaBeans 命名约定定义的。getter 名称将带有“get”,后跟属性名称,第一个字母大写。

包含更多信息的相关问题

于 2012-01-23T09:07:01.090 回答
0

当 javabean 引用“属性”时,它是带有 get() 和 set() 方法的东西。它不关心数据的内部存储是什么(如果有的话)。

因此,属性“foo”具有访问方法 getFoo() 和 setFoo(),这些方法的作用与属性的定义无关。

http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html

于 2012-01-23T09:07:56.457 回答