Вопрос-ответ

How to supply value to an annotation from a Constant java

Как предоставить значение аннотации из константы 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 [] для предоставления значения аннотации?

Переведено автоматически
Ответ 1

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


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


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



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

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

Ответ 3

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


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

Ответ 4

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

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

public class Values {
public static final String val0 = "A";
public static final String val1 = "B";

@SampleAnnotation(sampleValues={ val0, val1 })
public void foo() {
}
}
java arrays