Обнаружение настоящих аннотаций в данном объекте, переданных в конструктор - PullRequest
30 голосов
/ 06 декабря 2010

Короче, мой вопрос: как мне определить, присутствует ли (и в нужном ли) месте 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 и добавляются в список ячеек.

Мои вопросы:

  1. возможно ли обнаружить аннотации в этом объекте / классе во время выполнения и только для ЭТОГО переданного объекта (я не хочу сканировать аннотации в пути к классам!)?
  2. возможно лиопределить тип данных @Cell отмеченных элементов?Это необходимо, поскольку класс Cell не принимает все типы данных.
  3. можно ли получить фактическое имя члена (указанное в файле java), чтобы пользователю не приходилось указывать имя ячейки членов,Я хочу, чтобы пользователь мог писать @Cell (без имени) и @Cell(name="aName"), а когда указано только @Cell, вместо него используется имя члена.Я понятия не имею, если эта информация все еще доступна во время выполнения с помощью отражения.
  4. Как определить, находятся ли аннотации в нужном месте? Если код помечен так, то объект следует игнорировать (или, возможно,исключение брошено)?
    <code>@Cell // oh oh, that's no good :(
    public class WrongClass {
    // some members
    }
  5. Не могли бы вы предоставить код запуска, поэтому я немного знаю, как приступить к решению этой проблемы.Я действительно плохо знаком с аннотациями и размышлениями.Кстати, я использую последнюю версию JVM 1.6 +

Спасибо за вашу помощь!

Ответы [ 2 ]

43 голосов
/ 06 декабря 2010

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

  @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. Я не думаю, что вы можете сделать для аннотации значение по умолчанию, основанное на свойстве propertyName, но вы можете сделать имя необязательным, указав значение по умолчанию String name() default DEFAULT и проверив это значение при переборе полей и использованиизначение хранится в name() или propertyName

20 голосов
/ 06 декабря 2010

В.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,

...