Понимание аннотации в Java - PullRequest
11 голосов
/ 16 апреля 2011

Я пытался просмотреть некоторые онлайн-материалы, чтобы узнать аннотации в Java.

В следующем коде, что случилось с моей дорогой строкой "Hello world", которую я передал в этой строке: @Test_Target(doTestTarget="Hello World !")?

@Target(ElementType.METHOD)
public @interface Test_Target {
   public String doTestTarget();
}

выше - определенная аннотация, а ниже - ее использование

public class TestAnnotations {
   @Test_Target(doTestTarget="Hello World !")
   private String str;
   public static void main(String arg[]) {
      new TestAnnotations().doTestTarget();
   }
   public void doTestTarget() {
      System.out.printf("Testing Target annotation");
   }
}

Когда я запускаю этот код, он печатает только Testing Target annotation

Пожалуйста, помогите мне, я совершенно новичок в аннотации.

Ответы [ 3 ]

22 голосов
/ 16 апреля 2011

Аннотации - это, в основном, биты данных, которые вы можете прикрепить к полям, методам, классам и т. Д.

Синтаксис объявления аннотаций в Java немного неудобен. Они немного похожи на интерфейсы (в конце концов, они объявлены с @interface), но на самом деле они не являются интерфейсами. Я думаю, что вы могли бы поместить метод doTestTarget() в свой класс TestAnnotations, потому что вы думали, что ваша аннотация - это интерфейс, и вам нужно было его реализовать. Это не так - вы можете удалить этот метод и вызвать его из своего кода, если хотите, и это не вызовет у вас никаких проблем.

Кроме того, вы, возможно, не собирались помещать аннотацию в поле str. Аннотации применяются только к тому, что следует за ними. В результате ваш код не компилируется, потому что вы применили аннотацию к полю, но объявили, что ваша аннотация может быть применена только к методам. Измените @Target(ElementType.METHOD) на @Target(ElementType.FIELD), и ваш код должен скомпилироваться.

Что касается того, что происходит со строкой Hello World !, она записывается в файл .class и доступна любому инструменту, который читает в классах Java. Однако он не обязательно будет доступен в JVM во время выполнения. Это происходит потому, что вы не указали @Retention для аннотации @Test_Target. Значение по умолчанию для @Retention равно RetentionPolicy.CLASS, что означает, что JVM может не загружать их из файла класса. (См. Javadoc для перечисления RetentionPolicy .)

Я полагаю, вы хотите увидеть какой-нибудь способ чтения значения из этой аннотации во время выполнения. Если это так, я бы рекомендовал добавить @Retention(RetentionPolicy.RUNTIME) к аннотации, чтобы убедиться, что она будет доступна во время выполнения.

Чтобы получить доступ к аннотации и значению, содержащемуся в ней во время выполнения, вам нужно использовать отражение. Я переписал ваш класс TestAnnotations следующим образом для быстрой демонстрации:

import java.lang.reflect.Field;

public class TestAnnotations {

   @Test_Target(doTestTarget="Hello World !")
   private String str;

   public static void main(String[] args) throws Exception {
      // We need to use getDeclaredField here since the field is private.
      Field field = TestAnnotations.class.getDeclaredField("str");
      Test_Target ann = field.getAnnotation(Test_Target.class);
      if (ann != null) {
         System.out.println(ann.doTestTarget());
      }
   }
}

Когда я запускаю этот код, он дает мне следующий вывод:

Hello World !
4 голосов
/ 16 апреля 2011

В принципе, добавление аннотации само по себе принципиально не меняет поведение программ.

В вашем случае вы создали новый тип аннотации @Test_Target, который можно использовать в любом методе (как указано в его аннотации @Target).

Затем вы применили это не к методу, а к полю str (которое, я думаю, должно дать ошибку компилятора).

Независимо от этого вы создаете объект с помощью метода doTestTarget, вызываете его и получаете ожидаемый результат (т. Е. Метод выполняется).

Если вы хотите, чтобы ваша аннотация делала нечто большее, чем просто находилась там и предоставляла некоторую информацию для читателя источника, вы должны использовать ее - либо с процессором аннотации во время компиляции, либо с помощью отражения во время выполнения (тогда вам также понадобится @Retention(RUNTIME) в качестве аннотации к Test_Target.)

1 голос
/ 20 марта 2013

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

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface Test_Target {
   public String doTestTarget() default "default string";
}

, затем аннотируйте интерфейс, созданный для вашего класса.В вашем классе найдите аннотированный класс и затем вызовите метод с ним.

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;

@Test_Target(doTestTarget="Hello World !")
public class TestAnnotations {

public static void main(String[] args) throws Exception 
{      
    AnnotatedElement c = TestAnnotations.class;
    if(c.isAnnotationPresent(Test_Target.class))
    {
        Annotation singleAnnotation = c.getAnnotation(Test_Target.class);
        Test_Target tt = (Test_Target) singleAnnotation;
        System.out.println(tt.doTestTarget());
    }       
}

}

результат: Hello World!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...