识别 IType 的所有 IMethods 的访问器和修改器 (getters/setters)

Identifying accessors and mutators (getters/setters) of all IMethods of an IType

我可以使用方法 getMethods() 访问 IType 的所有方法。有没有一种有效的方法来确定这样的 IMethod 是访问器还是修改器 (getter/setter)?

检查 IMethod 的名称是否与方案 prefix + NameOfAttributeprefix ∈ {"get", "set", "is"} 匹配将帮助我检测明显的方案,但是如果访问器或修改器 (getter/setter) 不是那样命名的,它不会工作。

有没有更好的方法?

编辑:我只想识别直接get/set IType 属性的getter/setter 方法,不做任何其他事情.

EDIT2:使用的技术术语:accessor & mutator

EDIT3:这是我阅读所有答案后的解决方案

    private boolean isAccessor(IMethod method) throws JavaModelException {
        if (isAccessMethod("get", method) || isAccessMethod("is", method)) { // if name fits
            return method.getNumberOfParameters() == 0 && !Signature.SIG_VOID.equals(method.getReturnType());
        }
        return false;
    }

    private boolean isMutator(IMethod method) throws JavaModelException {
        if (isAccessMethod("set", method)) { // if name fits
            return method.getNumberOfParameters() == 1 && Signature.SIG_VOID.equals(method.getReturnType());
        }
        return false;
    }

    private boolean isAccessMethod(String prefix, IMethod method) throws JavaModelException {
        IType type = method.getDeclaringType();
        for (IField field : type.getFields()) { // for ever field of IType:
            if (method.getElementName().equalsIgnoreCase(prefix + field.getElementName())) {
                return true; // is access method if name scheme fits for one field
            }
        }
        return false; // is not an access method if no field fits
    }

重要提示:此解决方案符合我的要求,但忽略了一些重要情况(请参阅 。这仍然不检查该方法的功能,但它工作得很好。它检查我提出的方案的方法名称。但它还会检查参数计数以及 return 类型是否为 void。如果有人想对此进行改进,他还可以检查 getter 的 return/parameter 类型是否与与方法名称匹配的字段类型相匹配。

我的方法是:

for (IMethod m : iType.getMethods()) {
    if (m.getElementName().substring(0,3).equals("get")) {
        //do something
    } else if (m.getElementName().substring(0,3).equals("set")) {
        //do something else
    }
}

您可以在 IType 上使用 getFields(),然后在每个字段上使用 getElementName()

我猜 JDT 核心不支持识别 getters 和 setter。

JDT 中只有 public API 提供了 getter/setter 基于字段名称的名称生成。例如。 NamingConvention Take a look at the suggestGetterName() 方法。

其他内部 class 类似 GetterSetterUtil 也没有提供您想要的方法。

最后我会自己创建一个 属性 访问器检测器。也许作为过滤器我可以应用于 Collections.

Checking if the name of an IMethod matches the scheme prefix + NameOfAttribute with prefix ∈ {"get", "set"}

如果是布尔值 属性,还要检查 is 前缀和方法的参数列表。 Getters 通常不带参数,而 setter 通常带一个参数。我说通常,因为 JavaBeans specification 也允许索引属性。例如

 void setter(int index, PropertyType value); // indexed setter
 PropertyType getter(int index); // indexed getter
 void setter(PropertyType values[]); // array setter
 PropertyType[] getter(); // array getter

编辑

I added my own solution based on your proposals to my post.

您的解决方案可能符合您的要求。请记住,属性 可能没有直接的 backing-field。 属性 的概念有点抽象。我的意思是,如果你有一个名为 visible 的 属性 和一个 getter isVisible(),那么 class 可能没有字段 private boolean visible.

为了清楚起见,您应该查看 JComponent 中的 属性 rootPane。肯定是属性,因为Introspectorreturns而已。

BeanInfo jcomponentBeanInfo = Introspector.getBeanInfo(JComponent.class);

PropertyDescriptor[] propertyDescriptors = jcomponentBeanInfo.getPropertyDescriptors();
for (int i = 0; i < propertyDescriptors.length; i++) {
  PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
  if("rootPane".equals(propertyDescriptor.getName())){
    System.out.println("Found property rootPane");
    break;
  }
}

会打印出来

Found property rootPane

但如果您看一下实现,它不会直接使用 backing-field。

public JRootPane getRootPane() {
    return SwingUtilities.getRootPane(this);
}

SwingUtilities.getRootPane

public static JRootPane getRootPane(Component c) {
    if (c instanceof RootPaneContainer) {
        return ((RootPaneContainer)c).getRootPane();
    }
    for( ; c != null; c = c.getParent()) {
        if (c instanceof JRootPane) {
            return (JRootPane)c;
        }
    }
    return null;
}

我只是想让这个更清楚。