Jak dodać wartość do adnotacji z Constant java


146

Myślę, że może to nie być możliwe w Javie, ponieważ adnotacje i jej parametry są rozwiązywane w czasie kompilacji. Mam następujący interfejs,

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

i inna klasa jako,

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

Oznaczam wiele klas adnotacją i chciałbym wiedzieć, czy mogę uniknąć określania ciągów w każdej adnotacji, której wolałbym zamiast tego użyć

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

Jednak powoduje to błędy kompilacji, takie jak wartość adnotacji powinna być inicjatorem tablicy itp. Czy ktoś wie, jak mogę użyć stałej String lub stałej String [], aby podać wartość do adnotacji?

Odpowiedzi:


127

Stałe kompilacji mogą być tylko prymitywami i ciągami znaków :

15.28. Wyrażenia stałe

Wyrażenie stałe czasu kompilacji to wyrażenie oznaczające wartość typu pierwotnego lub String, które nie kończy się nagle i składa się tylko z następujących elementów:

  • Literały typu pierwotnego i literały typu String
  • Rzuty na typy pierwotne i rzuty na typy String
  • [...] operatorzy [...]
  • Wyrażenia w nawiasach, których wyrażenie zawarte jest wyrażeniem stałym.
  • Proste nazwy, które odnoszą się do stałych zmiennych.
  • Kwalifikowane nazwy w postaci TypeName . Identyfikator odnoszący się do zmiennych stałych.

W rzeczywistości w Javie nie ma sposobu na ochronę elementów w tablicy. W czasie wykonywania ktoś zawsze może to zrobić FieldValues.FIELD1[0]="value3", dlatego tablica nie może być naprawdę stała, jeśli spojrzymy głębiej.


14
Enum też! :) :)
TacB0sS

1
@ TacB0sS, wyliczenia nie są wyrażeniami stałymi.
jaco0646

Cóż ... może powinieneś spróbować i dać mi znać ... używam ich cały czas :)
TacB0sS

4
Bardziej odpowiednia specyfikacja znajduje się w sekcji Adnotacje . Oprócz wyrażenia stałego wartość adnotacji może być inicjatorem tablicy , literałem klasy lub stałą wyliczenia .
jaco0646

3
@ TacB0sS można używać enumw adnotacjach, ale nie są one stałymi w czasie kompilacji. Różnica staje się widoczna, gdy piszesz static final EnumType VARIABLE = EnumType.ENUM_CONSTANT;i próbujesz użyć VARIABLEw adnotacji; to nie zadziała. Możesz używać tylko tego, EnumType.ENUM_CONSTANTco nie jest wyrażeniem stałym, ale jest dozwolone w adnotacjach (i switchinstrukcjach).
Holger,

37

Możesz użyć stałej (tj. Statycznej, końcowej zmiennej) jako parametru adnotacji. Jako szybki przykład, dość często używam czegoś takiego:

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);
    }
}

Zwróć uwagę, że możliwe jest przekazanie TEST_TIMEOUTstałej bezpośrednio do adnotacji.

Z drugiej strony, nie przypominam sobie, że kiedykolwiek próbowałem tego z tablicą, więc możesz napotkać pewne problemy z niewielkimi różnicami w sposobie reprezentowania tablic jako parametrów adnotacji w porównaniu ze zmiennymi Java? Ale jeśli chodzi o drugą część twojego pytania, zdecydowanie możesz użyć stałego ciągu bez żadnych problemów.

EDIT: Właśnie próbowałem to z tablicy ciągów i nie napotkasz problem pan wspomniał - jednak kompilator nie mów mi, że „wartość atrybutu musi być stałe” mimo tablica jest określona jako public static final String[]. Może nie podoba mu się fakt, że tablice są zmienne? Hmm ...


1
Trudne dla mnie szczęście! O tak, udało mi się przekazać ciągi / liczby, ale nie tablice.
Spędzę

Tak, przypuszczam, że problemem jest tutaj zmienność tablicy FIELD1. Możesz zadeklarować tablicę za pomocą inicjatora tablicy, ponieważ nic innego nie może mieć dostępu do tej tablicy i nie można jej później zmienić.
ColinD

To rozwiązuje mój problem. Wystarczyło udostępnić stałą typu String między adnotacjami a kodem. Dzięki!
simon

1
statyczna zmienna końcowa nie jest jedynym warunkiem wstępnym. Jeśli spróbujesz dynamicznie obliczyć zmienną, otrzymasz ten sam komunikat o błędzie.
Wolfgang Fahl

11

W swoim przykładzie nie dostarczasz jej z tablicą. Następujące kompilacje dobrze:

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

4
W przykładzie jest dostarczana z tablicą, ale nie taką, która jest tworzona bezpośrednio w deklaracji adnotacji.
ColinD,

7

Czy ktoś wie, jak mogę użyć stałej String lub stałej String [], aby podać wartość do adnotacji?

Niestety nie możesz tego zrobić z tablicami. W przypadku zmiennych niebędących tablicami wartość musi być ostateczną wartością statyczną.


5

Myślę, że może to nie być możliwe w Javie, ponieważ adnotacje i jej parametry są rozwiązywane w czasie kompilacji.

Z Seam 2 http://seamframework.org/ można było rozwiązać parametry adnotacji w czasie wykonywania, używając języka wyrażeń w cudzysłowach.

W Seam 3 http://seamframework.org/Seam3/Solder ta funkcja to moduł Seam Solder


3
Nie, nie rozwiązałeś parametrów w czasie wykonywania. Parametr został rozwiązany w czasie kompilacji. Fakt, że zostały następnie użyte do zrobienia czegoś w czasie wykonywania, nie ma dosłownie nic wspólnego z ustawieniem ich wartości.
Załóż pozew Moniki

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.