Come fornire valore a un'annotazione da un java costante


146

Sto pensando che questo potrebbe non essere possibile in Java perché l'annotazione e i suoi parametri vengono risolti al momento della compilazione. Ho un'interfaccia come segue,

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

e un'altra classe come

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

Contrassegno molte classi con l'annotazione e vorrei sapere se posso evitare di specificare le stringhe in ogni annotazione che preferirei invece usare

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

Tuttavia, ciò fornisce errori di compilazione come il valore di annotazione dovrebbe essere un inizializzatore di array, ecc. Qualcuno sa come posso usare una costante String o una costante String [] per fornire valore a un'annotazione?

Risposte:


127

Le costanti di compilazione possono essere solo primitive e stringhe :

15.28. Espressioni costanti

Un'espressione costante in fase di compilazione è un'espressione che indica un valore di tipo primitivo o una stringa che non si completa improvvisamente ed è composta utilizzando solo i seguenti:

  • Letterali di tipo primitivo e letterali di tipo String
  • Lancia a tipi primitivi e lancia a tipo String
  • [...] operatori [...]
  • Espressioni tra parentesi la cui espressione contenuta è un'espressione costante.
  • Nomi semplici che si riferiscono a variabili costanti.
  • Nomi qualificati del modulo TypeName . Identificatore che fa riferimento a variabili costanti.

In realtà in Java non c'è modo di proteggere gli oggetti in un array. In fase di esecuzione qualcuno può sempre fare FieldValues.FIELD1[0]="value3", quindi l'array non può essere veramente costante se guardiamo più in profondità.


14
Anche enum! :) :)
TacB0sS

1
@ TacB0sS, gli enum non sono espressioni costanti.
jaco0646,

Beh ... forse dovresti provare e fammi sapere ... Li uso sempre :)
TacB0sS

4
Una specifica più pertinente è sotto Annotazioni . Oltre a un'espressione costante, un valore annotazione può essere una matrice inizializzatore , classe letterale , o costante enum .
jaco0646,

3
@ TacB0sS è possibile utilizzare enumnelle annotazioni, ma non sono costanti di tempo di compilazione. La differenza diventa evidente quando si scrive static final EnumType VARIABLE = EnumType.ENUM_CONSTANT;e si tenta di utilizzare VARIABLEin un'annotazione; non funzionerà. È possibile utilizzare solo EnumType.ENUM_CONSTANTespressioni non costanti, ma specificatamente consentite in annotazioni (e switchistruzioni).
Holger,

37

È possibile utilizzare una costante (ovvero una variabile finale statica) come parametro per un'annotazione. Come esempio veloce, uso una cosa del genere abbastanza spesso:

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

Nota che è possibile passare la TEST_TIMEOUTcostante direttamente nell'annotazione.

Sinceramente, non ricordo di aver mai provato questo con un array, quindi potresti riscontrare alcuni problemi con lievi differenze nel modo in cui gli array sono rappresentati come parametri di annotazione rispetto alle variabili Java? Ma per quanto riguarda l'altra parte della tua domanda, puoi sicuramente usare una stringa costante senza problemi.

EDIT: Ho appena provato questo con un array di stringhe, e non è stato eseguito nel problema lei ha citato - tuttavia il compilatore ha dirmi che il "valore di attributo deve essere costante", nonostante la matrice viene definita come public static final String[]. Forse non gli piace il fatto che le matrici siano mutabili? Hmm ...


1
Fortuna per me! Oh yah sono stato in grado di passare stringhe / numeri ma non array. Trascorrerò un po 'più di tempo su questo e se nulla funziona accetterà la risposta :)
Kannan Ekanath

Sì, la mia ipotesi sarebbe che la mutabilità dell'array FIELD1 sia il problema qui. Puoi dichiarare l'array con un inizializzatore di array perché nient'altro può avere accesso a quell'array e quindi non può essere modificato in seguito.
ColinD,

Questo risolve il mio problema. Ho solo bisogno di condividere una costante String tra annotazioni e codice. Grazie!
simon,

1
la variabile finale statica non è l'unico prerequisito. Se provi a calcolare dinamicamente la variabile otterrai lo stesso messaggio di errore.
Wolfgang Fahl,

11

Nel tuo esempio non lo stai fornendo con un array. Le seguenti compilazioni vanno bene:

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
Nell'esempio viene fornito un array, ma non uno creato direttamente nella dichiarazione di annotazione.
ColinD,

7

Qualcuno sa come posso usare una costante String o una costante String [] per fornire valore a un'annotazione?

Sfortunatamente, non puoi farlo con le matrici. Con variabili non array, il valore deve essere statico finale.


5

Sto pensando che questo potrebbe non essere possibile in Java perché l'annotazione e i suoi parametri vengono risolti al momento della compilazione.

Con Seam 2 http://seamframework.org/ sei riuscito a risolvere i parametri di annotazione in fase di esecuzione, con il linguaggio delle espressioni racchiuso tra virgolette doppie.

In Seam 3 http://seamframework.org/Seam3/Solder , questa funzione è il modulo Seam Solder


3
No, non hai risolto i parametri in fase di esecuzione. Il parametro è stato risolto in fase di compilazione. Il fatto che siano stati quindi utilizzati per eseguire operazioni in fase di esecuzione non ha letteralmente nulla a che fare con l'impostazione dei loro valori.
Finanzi la causa di Monica il

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.