Как поставить значение для аннотации из константы Java

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

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

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

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

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

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

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

5 ответов

Решение

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

15,28. Постоянные выражения

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

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

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

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

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? Но что касается другой части вашего вопроса, вы можете без проблем использовать постоянную строку.

РЕДАКТИРОВАТЬ: я только что попробовал это с массивом String, и не столкнулся с проблемой, которую вы упомянули - однако компилятор сказал мне, что "значение атрибута должно быть постоянным", несмотря на то, что массив определяется как public static final String[], Возможно, ему не нравится тот факт, что массивы изменчивы? Хм...

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

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

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

   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() {
        }
    }

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

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

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

Вы можете использовать enum и ссылаться на это перечисление в поле аннотации

Другие вопросы по тегам