Как указать значение аннотации из константы java

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

public interface FieldValues {
   String[] FIELD1 = new String[]{"value1", "value2"};
}

и другой класс as,

@SomeAnnotation(locations = {"value1", "value2"})
public class MyClass {
   ....
}

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

@SomeAnnotation(locations = FieldValues.FIELD1)
public class MyClass {
   ....
}

Однако это дает ошибки компиляции, такие как значение аннотации, должно быть инициализатором массива и т.д. Кто-нибудь знает, как я могу использовать константу String или константу String [] для предоставления значения аннотации?

Ответ 1

Компилировать константы могут быть только примитивами и строками:

15.28. Константные выражения

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

  • Литералы примитивного типа и литералов типа String
  • Отбрасывает примитивные типы и приведения типа String
  • [...] операторы [...]
  • Обозначенные в скобках выражения, содержащее выражение, которое является постоянным выражением.
  • Простые имена, относящиеся к постоянным переменным.
  • Квалифицированные имена формы TypeName. Идентификатор, который ссылается на постоянные переменные.

На самом деле в java нет способа защитить элементы в массиве. Во время выполнения кто-то всегда может делать FieldValues.FIELD1[0]="value3", поэтому массив не может быть действительно постоянным, если мы посмотрим глубже.

Ответ 2

В качестве параметра для аннотации вы можете использовать константу (то есть статическую, конечную переменную). В качестве быстрого примера я использую что-то подобное довольно часто:

import org.junit.Test;
import static org.junit.Assert.*;

public class MyTestClass
{
    private static final int TEST_TIMEOUT = 60000; // one minute per test

    @Test(timeout=TEST_TIMEOUT)
    public void testJDK()
    {
        assertTrue("Something is very wrong", Boolean.TRUE);
    }
}

Обратите внимание, что можно передать константу TEST_TIMEOUT прямо в аннотацию.

Оффлайн, я не помню, чтобы когда-либо пробовал это с помощью массива, вы можете столкнуться с некоторыми проблемами с небольшими различиями в том, как массивы представлены в виде параметров аннотации по сравнению с переменными Java? Но что касается другой части вашего вопроса, вы можете определенно использовать постоянную строку без каких-либо проблем.

EDIT: Я только что попробовал это с массивом String и не столкнулся с проблемой, о которой вы говорили, однако компилятор сказал мне, что значение атрибута должно быть постоянным, несмотря на то, что массив определяется как public static final String[]. Может быть, ему не нравится тот факт, что массивы изменяемы? Хм...

Ответ 3

Вы не снабжаете его массивом в вашем примере. Следующие компилируются:

   public @interface SampleAnnotation {
        String[] sampleValues();
    }

    public class Values {
        public static final String v1 = "A";
        public static final String v2 = "B";

        @SampleAnnotation(sampleValues = { v1, v2 })
        public void foo() {
        }
    }

Ответ 4

Кто-нибудь знает, как я могу использовать Константа строки или константа String [] указать значение аннотации?

К сожалению, вы не можете сделать это с помощью массивов. С переменными без массива значение должно быть окончательным.

Ответ 5

Я думаю, что это может быть невозможно в Java, потому что аннотация и ее параметры > разрешены во время компиляции.

С Seam 2 http://seamframework.org/ вы смогли разрешить параметры аннотации во время выполнения, причем язык выражений внутри двойных кавычек.

В Seam 3 этой функцией является модуль Seam Solder http://seamframework.org/Seam3/Solder