Java 识别一个IType的所有IMethods的访问器和变异器(getter/setter)
我可以使用方法Java 识别一个IType的所有IMethods的访问器和变异器(getter/setter),java,eclipse,parsing,abstract-syntax-tree,eclipse-jdt,Java,Eclipse,Parsing,Abstract Syntax Tree,Eclipse Jdt,我可以使用方法getMethods()访问IType的所有方法。有没有一种有效的方法来确定这样的i方法是存取器还是变异器(getter/setter) 检查i方法的名称是否与带有前缀的scheme前缀+NameOfAttribute匹配∈ {“get”、“set”、“is”}将帮助我检测明显的错误,但是如果访问器或变异器(getter/setter)没有这样命名,它将无法工作 有更好的办法吗 EDIT:我只想识别直接获取/设置IType属性的getter/setter方法,而不做任何其他事情 E
getMethods()
访问IType
的所有方法。有没有一种有效的方法来确定这样的i方法是存取器还是变异器(getter/setter)
检查i方法的名称是否与带有前缀的scheme前缀+NameOfAttribute
匹配∈ {“get”、“set”、“is”}
将帮助我检测明显的错误,但是如果访问器或变异器(getter/setter)没有这样命名,它将无法工作
有更好的办法吗
EDIT:我只想识别直接获取/设置IType
属性的getter/setter方法,而不做任何其他事情
EDIT2:使用的技术术语:存取器和变异器
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
}
重要提示:此解决方案符合我的要求,但忽略了一些重要情况(请参见)。这仍然无法检查该方法的功能,但效果相当不错。它检查我提出的方案的方法名。但它还检查参数计数以及返回类型是否为void
。如果有人想改进这一点,他还可以检查getter的返回/参数类型是否与方法名匹配的字段类型匹配。我的方法是:
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核心中不支持识别getter和setter
JDT中只有一个公共API提供基于字段名的getter/setter名称生成。看看这个方法
其他内部类,如GetterSetterUtil
也不提供所需的方法
最后,我将自己创建一个属性访问器检测器。也许作为一个过滤器,我可以应用于Collection
s
检查IMethod的名称是否与scheme prefix+NameOfAttribute with prefix匹配∈ {“获取”、“设置”}
对于布尔属性和方法的参数列表,还要检查is
前缀。getter通常不接受参数,而setter通常只接受一个参数。我通常说,因为也允许索引属性。例如
void setter(int index, PropertyType value); // indexed setter
PropertyType getter(int index); // indexed getter
void setter(PropertyType values[]); // array setter
PropertyType[] getter(); // array getter
编辑
我根据你的建议在我的帖子中添加了我自己的解决方案
您的解决方案可能符合您的要求。请记住,属性可能没有直接支持字段。属性的概念有点抽象。我的意思是,如果您有一个名为visible
的属性和一个getterisVisible()
类可能没有一个字段private boolean visible
为了清楚起见,您应该查看JComponent
中的属性rootPane
。它肯定是一个属性,因为用户返回它
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;
}
}
但是,如果您查看实现,它不会使用直接支持字段
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;
}
我只想说得更清楚。这与我在问题中提出的建议非常相似。问题是,如果该方法不是getter,而是名为getXYZ()
,它将被错误地声明为getter。您可以通过调用getFields()
来获取已声明字段的数组。然后为每个循环使用一个for(Field:iType.getFields())
。是的,但这仍然只检查方法的名称。这将是一个不错的解决方案,但也许有一种方法可以用JDTAPI检查方法的功能。感谢关于is前缀的提示,我会忘记的!另外,参数计数也是一个好主意。我根据你的建议在我的帖子中添加了我自己的解决方案。谢谢你的更新。这是一个有趣的例子,这使得准确识别访问器和变异器变得更加困难。我的解决方案可能符合我的要求,但并不是这个问题的通用解决方案。我将在我的帖子中添加这一点作为免责声明。
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;
}