Saya mencoba menampar dua atau lebih penjelasan dari jenis yang sama pada satu elemen, dalam hal ini, metode. Berikut perkiraan kode yang saya kerjakan:
public class Dupe {
public @interface Foo {
String bar();
}
@Foo(bar="one")
@Foo(bar="two")
public void haha() {}
}
Saat menyusun penjelasan di atas, javac mengeluh tentang anotasi duplikat:
max @ upsight: ~ / work / daybreak $ javac Dupe.java Dupe.java:5: anotasi duplikat
Apakah tidak mungkin mengulangi penjelasan seperti ini? Ngomong-ngomong, bukankah kedua contoh @Foo di atas berbeda karena isinya berbeda?
Jika hal di atas tidak memungkinkan, apa sajakah solusi potensial?
UPDATE: Saya telah diminta untuk menjelaskan kasus penggunaan saya. Ini dia.
Saya sedang membangun mekanisme sintaksis untuk "memetakan" POJO ke penyimpanan dokumen seperti MongoDB. Saya ingin mengizinkan indeks ditetapkan sebagai anotasi pada pengambil atau penyetel. Inilah contoh yang dibuat-buat:
public class Employee {
private List<Project> projects;
@Index(expr = "project.client_id")
@Index(expr = "project.start_date")
public List<Project> getProjects() { return projects; }
}
Jelas, saya ingin dapat dengan cepat menemukan contoh Karyawan berdasarkan berbagai properti Project. Saya dapat menentukan @Index dua kali dengan nilai expr () yang berbeda, atau mengambil pendekatan yang ditentukan dalam jawaban yang diterima. Meskipun Hibernate melakukan ini dan itu tidak dianggap sebagai peretasan, saya pikir masih masuk akal untuk setidaknya mengizinkan memiliki beberapa anotasi dengan jenis yang sama pada satu elemen.
sumber
Jawaban:
Dua atau lebih anotasi dengan jenis yang sama tidak diperbolehkan. Namun, Anda bisa melakukan sesuatu seperti ini:
public @interface Foos { Foo[] value(); } @Foos({@Foo(bar="one"), @Foo(bar="two")}) public void haha() {}
Anda akan membutuhkan penanganan khusus untuk anotasi Foos dalam kode.
btw, saya baru saja menggunakan ini 2 jam yang lalu untuk mengatasi masalah yang sama :)
sumber
@Foos([@Foo(bar="one"), @Foo(bar="two")])
. Lihat groovy.codehaus.org/Annotations+with+GroovyMengulangi anotasi di Java 8
Di Java 8 (dirilis pada Maret 2014), dimungkinkan untuk menulis anotasi berulang / duplikat.
Lihat tutorial, Anotasi Berulang .
Lihat spesifikasi, JEP 120: Anotasi Berulang .
sumber
Terlepas dari cara-cara lain yang disebutkan, ada satu lagi cara yang lebih sedikit di Java8:
@Target(ElementType.TYPE) @Repeatable(FooContainer.class) @Retention(RetentionPolicy.RUNTIME) @interface Foo { String value(); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface FooContainer { Foo[] value(); } @Foo("1") @Foo("2") @Foo("3") class Example{ }
Contoh secara default mendapat,
FooContainer
sebagai AnnotationKedua cetakan di atas:
sumber
http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html
Mulai dari Java8, Anda dapat mendeskripsikan anotasi berulang:
@Repeatable(FooValues.class) public @interface Foo { String bar(); } public @interface FooValues { Foo[] value(); }
Catatan,
value
bidang wajib diisi untuk daftar nilai.Sekarang Anda dapat menggunakan anotasi yang mengulanginya daripada mengisi array:
@Foo(bar="one") @Foo(bar="two") public void haha() {}
sumber
Seperti yang dikatakan oleh sfussenegger, ini tidak mungkin.
Solusi yang biasa adalah membuat anotasi "multipel" , yang menangani larik anotasi sebelumnya. Ini biasanya dinamai sama, dengan akhiran 's'.
Ngomong-ngomong, ini sangat digunakan dalam proyek publik besar (Hibernate misalnya), jadi tidak boleh dianggap sebagai peretasan, melainkan solusi yang tepat untuk kebutuhan ini.
Bergantung pada kebutuhan Anda, akan lebih baik jika anotasi Anda sebelumnya menangani beberapa nilai .
Contoh:
public @interface Foo { String[] bars(); }
sumber
menggabungkan jawaban lain ke dalam bentuk yang paling sederhana ... anotasi dengan daftar nilai sederhana ...
@Foos({"one","two"}) private String awk; //... public @interface Foos{ String[] value(); }
sumber
Jika Anda hanya memiliki 1 parameter "bar", Anda dapat menamainya sebagai "nilai". Dalam hal ini Anda tidak perlu menulis nama parameter sama sekali saat Anda menggunakannya seperti ini:
@Foos({@Foo("one"), @Foo("two")}) public void haha() {}
sedikit lebih pendek dan lebih rapi, imho ..
sumber
Di versi Java saat ini, saya dapat menyelesaikan masalah ini dengan anotasi berikut:
@Foo({"one", "two"})
sumber