定数Javaから注釈に値を提供する方法


146

アノテーションとそのパラメーターはコンパイル時に解決されるため、これは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 []定数を使用して注釈に値を提供する方法を誰かが知っていますか?

回答:


126

コンパイル定数はプリミティブと文字列のみにすることができます

15.28。定数式

コンパイル時の定数式は、プリミティブ型の値または文字列が突然完了せず、次のものだけを使用して構成される値を表すです。

  • プリミティブ型のリテラルと型のリテラル String
  • プリミティブ型へのキャストと型へのキャスト String
  • [...]演算子[...]
  • 含まれる式が定数式である括弧で囲まれた式。
  • 定数変数を参照する単純な名前。
  • TypeName形式の修飾名。定数変数を参照する識別子

実際にはJavaでは、配列内のアイテムを保護する方法はありません。実行時に誰かがいつでもできるFieldValues.FIELD1[0]="value3"ので、より深く見ると、配列は実際には一定ではありません。


14
列挙型も!:) :)
TacB0sS 2012

1
@ TacB0sS、列挙型は定数式ではありません。
jaco0646 2015年

まあ...多分あなたはそれをやってみて私に知らせるべきです...私はいつもそれらを使います:)
TacB0sS

4
より適切な仕様は、注釈の下にあります。定数式に加えて、注釈値には、配列初期化子クラスリテラル、または列挙定数を使用できます。
jaco0646

3
@ TacB0sS enumは注釈で使用できますが、コンパイル時の定数ではありません。違いを記述して注釈でstatic final EnumType VARIABLE = EnumType.ENUM_CONSTANT;使用しようとすると、明らかになりますVARIABLE。動作しません。使用できるのEnumType.ENUM_CONSTANTは定数式ではなく、注釈(およびswitchステートメント)でのみ許可されています。
Holger 2018

37

定数(つまり、静的な最終変数)を注釈のパラメーターとして使用できます。簡単な例として、私はこのようなものをかなり頻繁に使用します:

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[]。おそらく、配列が変更可能であるという事実が気に入らないのでしょうか?うーん...


1
頑張って!ああ、文字列/数値を渡すことはできましたが、配列を渡すことはできませんでした。私はこれにもう少し時間を費やし、
うまくいか

ええ、私の推測では、FIELD1配列の可変性が問題です。配列イニシャライザーを使用して配列を宣言することは許可されています。これは、他にその配列にアクセスできないため、後で変更できないためです。
ColinD 2010年

これは私の問題を解決します。注釈とコードの間で文字列定数を共有するために必要なだけです。ありがとう!
サイモン、

1
static final変数が唯一の前提条件ではありません。変数を動的に計算しようとすると、同じエラーメッセージが表示されます。
Wolfgang Fahl 2017年

11

あなたの例では配列を提供していません。以下は正常にコンパイルされます:

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
この例では、アノテーション宣言で直接作成された配列ではなく、配列が提供されています。
ColinD 2010年

7

誰かが文字列定数またはString []定数を使用して注釈に値を提供する方法を知っていますか?

残念ながら、これを配列で行うことはできません。非配列変数の場合、値はfinal staticでなければなりません。


5

アノテーションとそのパラメーターはコンパイル時に解決されるため、これはJavaでは不可能かもしれないと思います。

Seam 2 http://seamframework.org/を使用すると、式の言語を二重引用符で囲んで、実行時に注釈パラメーターを解決できました。

Seam 3 http://seamframework.org/Seam3/Solderでは、この機能はSeam Solderモジュールです


3
いいえ、実行時にパラメーターを解決しませんでした。パラメータはコンパイル時に解決されました。それらが実行時に何かをするために使用されたということは、それらの値が設定されたときに文字通り何の関係もありません。
モニカの訴訟に資金を

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.