我有一个自定义注释,我想在运行时使用它来显示对象属性。我希望它们以源代码顺序出现,但反射不保证Class.getMethods()
的任何特定顺序。
有没有办法,通过反射或通过注释处理,以源顺序获取方法(至少每个类,如果涉及多个继承级别)?
举个例子,假设我有一个界面Property
package test;
public @interface Property {
public String name();
}
和使用该注释的类
package test;
public class MyObject {
@Property(name = "First")
public void getFirst() {}
@Property(name = "Another")
public void getAnother() {}
}
我想在属性“Another”之前可靠地获得“First”属性。
我知道我可以在我的注释中添加一个排序属性并对其进行排序但是我有很多需要更新的类,如果这是必需的,所以我正在寻找一种通用的方法来实现这一点而不需要修改个体注释
答案 0 :(得分:2)
如果您将注释收集到List<Property>
,则可以使用List
与任何其他收藏集一样订购Collections.sort(collection, comparator)
。主要问题是如何排序注释没有自然顺序,因此您需要定义此顺序。我已通过比较器中使用的List
定义了订单。
public class MyObject {
@Property(name = "First")
public void getFirst() {
}
@Property(name = "Another")
public void getAnother() {
}
@Property(name = "Last")
public void getLast() {
}
public static void main(String[] args) {
Method[] methods = MyObject.class.getDeclaredMethods();
List<Property> properties = new ArrayList<Property>();
for(Method method: methods){
if(method.isAnnotationPresent(Property.class)){
properties.add(method.getAnnotation(Property.class));
}
}
for(Property property:properties){
System.out.println(property.name());
}
Collections.sort(properties, new Comparator<Property>(){
List<String> order = Arrays.asList("Last", "First", "Another");
@Override
public int compare(Property arg0, Property arg1) {
//Compare only considers the sign of result.
return (order.indexOf(arg0.name()) - order.indexOf(arg1.name()));
}
});
for(Property property:properties){
System.out.println(property.name());
}
}
}
答案 1 :(得分:2)
除非您愿意并且能够通过现有注释的附加注释或属性更改原始来源以强加订单,否则看起来这不可能通过反射实现。
然而,在注释处理期间可能。 TypeElement.getEnclosedElements()
的{{3}}表示
将以自然顺序返回所包含元素的列表,以获取有关该类型的原始信息源。例如,如果有关类型的信息源自源文件,则元素将以源代码顺序返回 [强调添加]。
要在运行时使其可用,您需要使用注释处理方法并存储可在运行时访问的某个位置(例如生成的资源文件)。