Cara memasok nilai ke anotasi dari java Konstan

146

Saya pikir ini tidak mungkin di Jawa karena anotasi dan parameternya diselesaikan pada waktu kompilasi. Saya memiliki antarmuka sebagai berikut,

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

dan kelas lain sebagai,

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

Saya menandai banyak kelas dengan anotasi dan saya ingin tahu apakah saya dapat menghindari menentukan string dalam setiap anotasi yang saya lebih suka gunakan

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

Namun ini memberikan kesalahan kompilasi seperti nilai penjelasan harus menjadi initializer array dll. Apakah ada yang tahu bagaimana saya bisa menggunakan konstanta String atau String [] konstan untuk memasok nilai ke anotasi?

Kannan Ekanath
sumber

Jawaban:

127

Kompilasi konstanta hanya dapat berupa primitif dan String :

15.28. Ekspresi Konstan

Ekspresi konstanta waktu kompilasi adalah ekspresi yang menunjukkan nilai tipe primitif atau String yang tidak lengkap secara tiba-tiba dan disusun hanya menggunakan yang berikut ini:

  • Literal tipe primitif dan literal tipe String
  • Melemparkan ke tipe primitif dan gips untuk mengetik String
  • operator [...] [...]
  • Ekspresi terkurung yang berisi ekspresi adalah ekspresi konstan.
  • Nama sederhana yang merujuk ke variabel konstan.
  • Nama-nama yang memenuhi syarat dari form TypeName . Identifier yang merujuk ke variabel konstan.

Sebenarnya di java tidak ada cara untuk melindungi item dalam array. Pada saat runtime seseorang selalu dapat melakukannya FieldValues.FIELD1[0]="value3", oleh karena itu array tidak dapat benar-benar konstan jika kita melihat lebih dalam.

tak dapat disangkal
sumber
14
Enums juga! :) :)
TacB0sS
1
@ TacB0sS, enum bukan ekspresi konstan.
jaco0646
Yah ... mungkin Anda harus mencobanya dan beri tahu saya ... Saya menggunakannya sepanjang waktu :)
TacB0sS
4
Spesifikasi yang lebih relevan ada di bawah Anotasi . Selain ekspresi konstan, nilai penjelasan dapat berupa penginisialisasi array , kelas literal , atau konstanta enum .
jaco0646
3
@ TacB0sS dapat Anda gunakan enumdalam annotatios, tetapi mereka tidak konstan waktu kompilasi. Perbedaannya menjadi jelas ketika Anda menulis static final EnumType VARIABLE = EnumType.ENUM_CONSTANT;dan mencoba menggunakannya VARIABLEdalam anotasi; itu tidak akan berhasil. Anda hanya dapat menggunakan EnumType.ENUM_CONSTANTyang bukan ekspresi konstan, tetapi secara khusus diizinkan dalam anotasi (dan switchpernyataan).
Holger
37

Anda dapat menggunakan konstanta (yaitu variabel statis, akhir) sebagai parameter untuk anotasi. Sebagai contoh cepat, saya sering menggunakan sesuatu seperti ini:

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

Perhatikan bahwa mungkin untuk lulus TEST_TIMEOUT konstanta langsung ke anotasi.

Begitu saja, saya tidak ingat pernah mencoba ini dengan sebuah array, jadi Anda mungkin mengalami beberapa masalah dengan sedikit perbedaan dalam bagaimana array direpresentasikan sebagai parameter anotasi dibandingkan dengan variabel Java? Tetapi untuk bagian lain dari pertanyaan Anda, Anda pasti bisa menggunakan String konstan tanpa masalah.

EDIT: Saya baru saja mencoba ini dengan array String, dan tidak mengalami masalah yang Anda sebutkan - namun kompiler itu memberi tahu saya bahwa "nilai atribut harus konstan" meskipun array didefinisikan sebagai public static final String[]. Mungkin tidak suka fakta bahwa array bisa berubah? Hmm ...

Andrzej Doyle
sumber
1
Keberuntungan yang sulit bagi saya! Oh ya saya bisa melewati Strings / Numbers tetapi tidak array. Saya akan menghabiskan sedikit lebih banyak waktu untuk hal ini dan jika tidak ada yang berhasil akan menerima jawabannya :)
Kannan Ekanath
Ya, tebakan saya adalah bahwa ketidakmampuan array FIELD1 adalah masalah di sini. Anda diperbolehkan mendeklarasikan array dengan inisialisasi array karena tidak ada yang dapat mengakses array itu sehingga tidak dapat diubah kemudian.
ColinD
Ini menyelesaikan masalah saya. Hanya perlu membagikan konstanta String antara anotasi dan kode. Terima kasih!
simon
1
variabel final statis bukan satu-satunya prasyarat. Jika Anda mencoba menghitung secara dinamis variabel Anda akan mendapatkan pesan kesalahan yang sama.
Wolfgang Fahl
11

Anda tidak menyediakannya dengan array dalam contoh Anda. Kompilasi berikut baik-baik saja:

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() {
    }
}
Steve B.
sumber
4
Itu disediakan dengan array dalam contoh, hanya saja tidak satu yang dibuat langsung dalam deklarasi anotasi.
ColinD
7

Apakah ada yang tahu bagaimana saya bisa menggunakan konstanta String atau konstanta String [] untuk memberikan nilai pada anotasi?

Sayangnya, Anda tidak dapat melakukan ini dengan array. Dengan variabel non-array, nilainya harus final statis.

Kevin
sumber
5

Saya pikir ini tidak mungkin di Jawa karena anotasi dan parameternya diselesaikan pada waktu kompilasi.

Dengan Seam 2 http://seamframework.org/ Anda dapat menyelesaikan parameter anotasi saat runtime, dengan bahasa ekspresi di dalam tanda kutip ganda.

Dalam Seam 3 http://seamframework.org/Seam3/Solder , fitur ini adalah modul Seam Solder

jorgwel
sumber
3
Tidak, Anda tidak menyelesaikan parameter saat runtime. Parameter diselesaikan pada waktu kompilasi. Bahwa mereka kemudian digunakan untuk melakukan sesuatu saat runtime secara harfiah tidak ada hubungannya dengan ketika nilai-nilai mereka ditetapkan.
Dana Gugatan Monica
1

Anda dapat menggunakan enum dan merujuk enum itu di bidang anotasi

Kaustubh Thawari
sumber
1
Anda harus menambahkan contoh.
m02ph3u5