Подтвердить что ты не робот

Обнаружение существующих аннотаций внутри данного объекта, переданных в конструктор

Мой вопрос вкратце: как определить, присутствует ли аннотация java (и в нужном месте) для данного пользовательского класса/объекта.

Подробности "проблемы"

Допустим, у меня есть два класса java:

public class Line {
   private List<Cell> cells;

   public Line(Object... annotatedObjects) {
     // check if annotations @Line and @Cell are present in annotatedObjects.
   }

   // getter/setter for cells.
}

public class Cell {
   // some members
   // some methods
}

Объект Line удерживает ячейки.

У меня также есть две аннотации, например:

public @interface Line {
  // some stuff here
}

public @interface Cell {
  // some stuff here
}

У меня также есть группа пользовательских классов (в этом примере будут два), которые содержат аннотации @Line и @Cell, которые я указал, например:

@Line(name="pqr", schema="three")
public class AUserClass {
   @Cell
   private String aString;
}

@Line(name="xyz", schema="four")
public class AnotherUserClass {
   @Cell(name="birthday")
   private Date aDate;
}

Проблема: когда я создаю экземпляр нового объекта Line, я хочу иметь возможность передавать пользовательские классы/объекты в конструктор Line. Конструктор Line затем выясняет, являются ли пройденные классы/объекты пользователем допустимыми классами, которые могут быть обработаны. Только пользовательские классы, которые имеют аннотацию @Line для класса и по крайней мере одну аннотацию @Cell для своих членов, являются допустимыми объектами, которые могут быть переданы в конструктор объекта Line. Все остальные переданные объекты недействительны. Когда передается действительный объект пользователя, все доступные члены, помеченные как @Cell в этом объекте, преобразуются в объекты Cell и добавляются в список ячеек.

Мои вопросы:

  • Это возможно обнаружить аннотации в этом объекте/классе во время выполнения, и только для этого переданного объекта (я не хочу сканировать аннотации в пути к классам!)?
  • Можно ли определить тип данных тегов @Cell? Это необходимо, потому что класс Cell не принимает все типы данных.
  • Можно ли получить фактическое имя участника (указанное в java файле), чтобы пользователь не должен был указывать члены. Я хочу, чтобы пользователь мог писать @Cell (без имени) и @Cell(name="aName"), и когда задано только @Cell, вместо этого используется имя члена. Я понятия не имею, доступна ли эта информация во время выполнения, используя отражение.
  • Как определить, находятся ли аннотации в нужном месте? Если код помечен таким образом, то объект должен быть проигнорирован (или, может быть, выбрано исключение)?
    @Cell // oh oh, that no good :(
    public class WrongClass {
    // some members
    }
  • Не могли бы вы предоставить код запуска, поэтому я немного знаю об этой проблеме. Я действительно новичок в комментариях и размышлениях. BTW: Я использую последнюю версию jvm 1.6 +

Спасибо за вашу любезную помощь!

4b9b3361

Ответ 1

Сначала вам нужно иметь политику хранения ваших аннотаций, чтобы вы могли читать их с отражением

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public static @interface Line {

  }

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.FIELD)
  public static @interface Cell {

  }

Во-вторых, вам нужно проверить, имеет ли класс аннотацию Line с isAnnotationPresent(annotationClass). Этот метод доступен из java.lang.Class и java.lang.reflect.Field.

ПРИМЕЧАНИЕ: вам нужно получить поля, закрытые с помощью class.getDeclaredField(fieldName).

3. Я не думаю, что вы можете сделать аннотацию, имеющую значение по умолчанию, основанное на имени свойства, но вы можете сделать имя необязательным, указав по умолчанию String name() default DEFAULT и проверить это значение при итерации по полям и использовать значение, сохраненное в name() или propertyName

Ответ 2

Q.1: возможно ли это обнаружить аннотации в этом объекте/классе во время выполнения и только для этого переданного объекта (я не хочу проверять аннотации в пути к классам!)?

Да, это очень возможно, используя isAnnotationPresent

@Deprecated
public class AnnotationDetection {

    public static void main(String[] args) {
        AnnotationDetection annotationDetection = new AnnotationDetection();
        System.out.println(annotationDetection.getClass().isAnnotationPresent(Deprecated.class));
    }
}

Примечание, что аннотация, которая ограничена для сохранения в Runtime, будет доступна только,