Сравните два объекта в Java, используя отражение и аннотации

1

У меня есть образец объекта Student, который имеет несколько полей (номер индекса, имя, фамилия и т.д.). Я хотел бы сравнить два объекта 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 overriden function body:

@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;
}

И теперь я застрял. Потому что в этот момент мне нужно решить, больше или меньше поле этого и другого ученика. И я не могу сделать это с помощью raw Object type, единственное, что я могу сделать, это метод equals, который недостаточно. Мне нужно знать, больше или меньше. Мне нужно как-то бросить... да, что именно? Как извлечь тип поля, а затем бросить? Это даже выполнимо?

PS. Я знаю, что, возможно, более простой подход - использовать аннотации методов и вызывать методы getter, но мне просто интересно, насколько это выполнимо, как я пытаюсь это сделать.

  • 0
    Если вы используете Java 8, вы можете составить компараторы в нужном вам порядке, избегая ненужных аннотаций и отражений.
  • 0
    Да, я знаю. Но мне специально нужно сделать это с помощью аннотации и отражения. Это упражнение;)
Показать ещё 3 комментария
Теги:
reflection
casting
annotations

2 ответа

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
    ++, поскольку это только упражнение, поля в примерах OP, скорее всего, будут реализациями Comparable (поскольку get возвращает экземпляры классов-оболочек), но давайте помнить, что не все классы реализуют этот интерфейс (например, коллекции).
  • 0
    Да, похоже, это помогает. Спасибо!
0

По мере того, как вы уже находитесь в размышлении, вы можете проверить, могут ли поля, которые вы комментируете, также реализовать интерфейс Comparable. Затем вы можете сравнить их с методом compareTo, который они реализуют.

Если у вас есть поле, которое аннотируется и не реализует Comparable, это должно быть ошибкой (можно ли ограничить аннотацию полями, реализующими специальный интерфейс?).

Измените int-поля на Integer и другие примитивные типы, а также на их сопоставления с объектами и не забудьте проверить нуль при сравнении.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню