Ikhtisar Anotasi Bawaan Java

1. Ikhtisar

Di artikel ini, kita akan berbicara tentang fitur inti bahasa Java - anotasi default yang tersedia di JDK.

2. Apa Itu Anotasi

Sederhananya, anotasi adalah jenis Java yang diawali dengan simbol “@” .

Java memiliki anotasi sejak rilis 1.5. Sejak itu, mereka telah membentuk cara kami mendesain aplikasi kami.

Spring dan Hibernate adalah contoh framework yang bagus yang sangat bergantung pada anotasi untuk mengaktifkan berbagai teknik desain.

Pada dasarnya, anotasi memberikan metadata tambahan ke kode sumber yang terikat padanya . Dengan menambahkan anotasi ke metode, antarmuka, kelas, atau bidang, kita dapat:

  1. Beri tahu kompiler tentang peringatan dan kesalahan
  2. Memanipulasi kode sumber pada waktu kompilasi
  3. Ubah atau periksa perilaku pada waktu proses

3. Anotasi Bawaan Java

Sekarang setelah kita meninjau dasar-dasarnya, mari kita lihat beberapa anotasi yang disertakan dengan inti Java. Pertama, ada beberapa yang menginformasikan kompilasi:

  1. @Mengesampingkan
  2. @Suppression
  3. @Tokopedia
  4. @Maniakbodong
  5. @FunctionalInface
  6. @Asli

Anotasi ini menghasilkan atau menyembunyikan peringatan dan kesalahan compiler. Menerapkannya secara konsisten sering kali merupakan praktik yang baik karena menambahkannya dapat mencegah kesalahan programmer di masa mendatang.

The @ Override penjelasan digunakan untuk menunjukkan bahwa metode menimpa atau mengganti perilaku metode diwariskan.

@SuppressWarnings menunjukkan bahwa kita ingin mengabaikan peringatan tertentu dari bagian kode. The @SafeVarargs penjelasan juga bertindak pada jenis peringatan yang terkait dengan menggunakan varargs.

The @Deprecated penjelasan dapat digunakan untuk menandai sebuah API tidak dimaksudkan untuk digunakan lagi. Selain itu, anotasi ini telah dipasang di Java 9 untuk menunjukkan informasi lebih lanjut tentang penghentian tersebut.

Untuk semua ini, Anda dapat menemukan informasi lebih rinci di artikel yang ditautkan.

3.1. @FunctionalInface

Java 8 memungkinkan kita untuk menulis kode dengan cara yang lebih fungsional.

Antarmuka Metode Abstrak Tunggal adalah bagian besar dari ini. Jika kami bermaksud antarmuka SAM untuk digunakan oleh lambda, kami secara opsional dapat menandainya dengan @FunctionalInterface :

@FunctionalInterface public interface Adder { int add(int a, int b); }

Seperti @Override dengan metode, @FunctionalInterface mendeklarasikan maksud kami dengan Adder .

Sekarang, apakah kita menggunakan @FunctionalInterface atau tidak, kita masih bisa menggunakan Adder dengan cara yang sama:

Adder adder = (a,b) -> a + b; int result = adder.add(4,5);

Tetapi, jika kita menambahkan metode kedua ke Adder, maka compiler akan mengeluh:

@FunctionalInterface public interface Adder { // compiler complains that the interface is not a SAM int add(int a, int b); int div(int a, int b); }

Sekarang, ini akan dikompilasi tanpa anotasi @FunctionalInterface . Jadi, apa manfaatnya bagi kita?

Seperti @Override , anotasi ini melindungi kita dari kesalahan programmer di masa mendatang. Meskipun legal untuk memiliki lebih dari satu metode pada sebuah antarmuka, itu bukan ketika antarmuka itu digunakan sebagai target lambda. Tanpa anotasi ini, kompilator akan merusak banyak tempat di mana Adder digunakan sebagai lambda. Sekarang, itu hanya rusak di Adder itu sendiri.

3.2. @Asli

Mulai Java 8, ada anotasi baru dalam paket java.lang.annotation bernama Native. The @Native penjelasan hanya berlaku untuk bidang. Ini menunjukkan bidang beranotasi adalah konstanta yang dapat dirujuk dari kode asli . Misalnya, berikut cara penggunaannya di kelas Integer :

public final class Integer { @Native public static final int MIN_VALUE = 0x80000000; // omitted }

Anotasi ini juga dapat berfungsi sebagai petunjuk bagi alat untuk menghasilkan beberapa file header tambahan.

4. Meta-Annotation

Selanjutnya, meta-annotation adalah anotasi yang dapat diterapkan pada anotasi lain.

Misalnya, meta-annotation berikut digunakan untuk konfigurasi anotasi:

  1. @Target
  2. @Penyimpanan
  3. @Warisan
  4. @Dokumen
  5. @Rumah

4.1. @Target

Cakupan anotasi dapat bervariasi berdasarkan persyaratan. Meskipun satu anotasi hanya digunakan dengan metode, anotasi lain dapat digunakan dengan konstruktor dan deklarasi bidang.

Untuk menentukan elemen target dari anotasi khusus, kita perlu menandainya dengan anotasi @Target .

@Target dapat bekerja dengan delapan jenis elemen yang berbeda. Jika kita melihat kode sumber @ SafeVarargs , maka kita dapat melihat bahwa itu hanya harus dilampirkan ke konstruktor atau metode:

@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.CONSTRUCTOR, ElementType.METHOD}) public @interface SafeVarargs { }

4.2. @Penyimpanan

Beberapa anotasi dimaksudkan untuk digunakan sebagai petunjuk bagi kompiler, sementara yang lain digunakan pada waktu proses.

Kami menggunakan anotasi @Retensi untuk mengatakan di mana dalam siklus hidup program kami, anotasi kami berlaku .

To do this, we need to configure @Retention with one of three retention policies:

  1. RetentionPolicy.SOURCE – visible by neither the compiler nor the runtime
  2. RetentionPolicy.CLASS – visible by the compiler
  3. RetentionPolicy.RUNTIME – visible by the compiler and the runtime

@Retention defaults to RetentionPolicy.SOURCE.

If we have an annotation that should be accessible at runtime:

@Retention(RetentionPolicy.RUNTIME) @Target(TYPE) public @interface RetentionAnnotation { }

Then, if we add some annotations to a class:

@RetentionAnnotation @Deprecated public class AnnotatedClass { }

Now we can reflect on AnnotatedClass to see how many annotations are retained:

@Test public void whenAnnotationRetentionPolicyRuntime_shouldAccess() { AnnotatedClass anAnnotatedClass = new AnnotatedClass(); Annotation[] annotations = anAnnotatedClass.getClass().getAnnotations(); assertThat(annotations.length, is(1)); }

The value is 1 because @RetentionAnnotation has a retention policy of RUNTIME while @Deprecated doesn't.

4.3. @Inherited

In some situations, we may need a subclass to have the annotations bound to a parent class.

We can use the @Inherited annotation to make our annotation propagate from an annotated class to its subclasses.

If we apply @Inherited to our custom annotation and then apply it to BaseClass:

@Inherited @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface InheritedAnnotation { } @InheritedAnnotation public class BaseClass { } public class DerivedClass extends BaseClass { }

Then, after extending the BaseClass, we should see that DerivedClass appears to have the same annotation at runtime:

@Test public void whenAnnotationInherited_thenShouldExist() { DerivedClass derivedClass = new DerivedClass(); InheritedAnnotation annotation = derivedClass.getClass() .getAnnotation(InheritedAnnotation.class); assertThat(annotation, instanceOf(InheritedAnnotation.class)); }

Without the @Inherited annotation, the above test would fail.

4.4. @Documented

By default, Java doesn't document the usage of an annotation in Javadocs.

But, we can use the @Documented annotation to change Java's default behavior.

If we create a custom annotation that uses @Documented:

@Documented @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ExcelCell { int value(); }

And, apply it to the appropriate Java element:

public class Employee { @ExcelCell(0) public String name; }

Then, the Employee Javadoc will reveal the annotation usage:

4.5. @Repeatable

Sometimes it can be useful to specify the same annotation more than once on a given Java element.

Before Java 7, we had to group annotations together into a single container annotation:

@Schedules({ @Schedule(time = "15:05"), @Schedule(time = "23:00") }) void scheduledAlarm() { }

However, Java 7 brought a cleaner approach. With the @Repeatable annotation, we can make an annotation repeatable:

@Repeatable(Schedules.class) public @interface Schedule { String time() default "09:00"; }

To use @Repeatable, we need to have a container annotation, too. In this case, we'll reuse @Schedules:

public @interface Schedules { Schedule[] value(); }

Of course, this looks a lot like what we had before Java 7. But, the value now is that the wrapper @Schedules isn't specified anymore when we need to repeat @Schedule:

@Schedule @Schedule(time = "15:05") @Schedule(time = "23:00") void scheduledAlarm() { }

Because Java requires the wrapper annotation, it was easy for us to migrate from pre-Java 7 annotation lists to repeatable annotations.

5. Conclusion

Pada artikel ini, kami telah membicarakan tentang anotasi bawaan Java yang harus dipahami oleh setiap pengembang Java.

Seperti biasa, semua contoh artikel dapat ditemukan di GitHub.