我有一个示例Student对象,它有几个字段(索引号,名称,姓氏等)。我想比较两个学生对象,但我想定义字段比较的优先级。为此,我使用字段注释,如下例所示:
注释界面定义:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CompareOrder {
int order();
}
用法:
@CompareOrder(order = 3)
private int indexNumber;
@CompareOrder(order = 2)
private String name;
@CompareOrder(order = 1)
private String familyName;
private ArrayList <Float> marks;
@CompareOrder(order = 5)
private float average;
@CompareOrder(order = 4)
private boolean fullTime;
某些字段不包含注释,并且在比较时会被忽略。我做的第一件事是使用反射提取类的所有字段,并根据比较顺序对它们进行排序,这对应于我的compareTo覆盖函数体的第一部分:
@Override
public int compareTo(Student other) {
// TODO Auto-generated method stub
Class<? extends Student> clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
List <Field> fieldList = new ArrayList<Field> ();
//ommiting unannotated fields
for (Field f : fields)
{
if(f.getAnnotation(CompareOrder.class) != null) fieldList.add(f);
}
//sorting fields by compare order
Collections.sort(fieldList, new Comparator <Field> (){
@Override
public int compare(Field f0, Field f1) {
CompareOrder compOrder0 = f0.getAnnotation(CompareOrder.class);
CompareOrder compOrder1 = f1.getAnnotation(CompareOrder.class);
return compOrder0.order() - compOrder1.order();
}
});
for (Field f : fieldList)
{
// HERE GOES COMPARISON OF OBJECTS FIELD BY FIELD, ACCORDING TO THE ORDERING
}
return 0;
}
现在我有点卡住了。因为在这一点上,我需要决定这个和其他学生的领域是更大还是更小。我不能用原始对象类型做到这一点,我唯一能做的就是调用equals方法,这是不够的。我需要知道它是大还是小。我需要以某种方式投射它......是的,到底是什么?如何提取字段类型,然后进行转换?这甚至可行吗?
PS。我知道,可能更简单的方法是使用方法注释并调用getter方法,但我只是好奇它是否可行,就像我尝试这样做一样。
答案 0 :(得分:1)
我认为你可以使用Class.isAssignableFrom(Class)
之类的东西,比如
Class<Comparable> cls = Comparable.class;
for (Field f : fieldList) {
if (cls.isAssignableFrom(f.getType())) {
Comparable c = (Comparable) f.get(this);
int r = c.compareTo((Comparable) f.get(other));
if (r != 0) {
return r;
}
}
}
答案 1 :(得分:0)
当您已经进入反射时,您可以检查您注释的字段是否也实现了Comparable接口。然后,您可以将它们与它们实现的compareTo方法进行比较。
如果您有一个带注释且未实现Comparable的字段,那么这应该是一个错误(是否可以将注释限制为实现特殊接口的字段?)。
将int字段更改为Integer,将其他原始类型更改为对象,并且在比较时不要忘记null检查。