Zrozumienie adnotacji Java — samouczek Java @adnotations
Opublikowany: 2019-10-22
Jak i gdzie są używane adnotacje w Javie?
Adnotacja w języku programowania Java jest specjalną formą metadanych składniowych, które można dodać do kodu źródłowego Java.
Klasy, metody, zmienne, parametry i pakiety mogą być opisywane. W przeciwieństwie do znaczników Javadoc adnotacje Java mogą być odzwierciedleniem, ponieważ mogą być osadzane w plikach klas generowanych przez kompilator i mogą być zachowywane przez maszynę wirtualną Java, aby można je było odzyskać w czasie wykonywania.
Możliwe jest tworzenie meta-adnotacji z istniejących w Javie, co czyni tę koncepcję bardziej wyrafinowaną.
Java definiuje zestaw adnotacji wbudowanych w język.

Adnotacje zastosowane do kodu Java:
- @Override — sprawdza, czy funkcja jest nadpisaniem. Powoduje ostrzeżenie kompilacji, jeśli funkcja nie zostanie znaleziona w jednej z klas nadrzędnych.
- @Deprecated — oznacza funkcję jako przestarzałą. Powoduje ostrzeżenie kompilacji, jeśli funkcja jest używana.
- @SuppressWarnings — nakazuje kompilatorowi pominięcie ostrzeżeń dotyczących czasu kompilacji określonych w parametrach adnotacji.
Adnotacje zastosowane do innych adnotacji:
- @Retention — określa, w jaki sposób oznaczona adnotacja jest przechowywana — tylko w kodzie, skompilowana do klasy lub dostępna w czasie wykonywania przez odbicie.
- @Documented – zaznacza kolejną adnotację do uwzględnienia w dokumentacji.
- @Target — zaznacza inną adnotację, aby ograniczyć rodzaj elementów Java, do których można zastosować adnotację.
- @Inherited – zaznacza inną adnotację, która ma być dziedziczona do podklas klasy z adnotacjami (domyślnie adnotacje nie są dziedziczone do podklas).
Przyjrzyjmy się tym za pomocą przykładowych przykładów:
1) Adnotacja @Override:
Jego obecność wskazuje kompilatorowi, że metoda z adnotacjami musi zastąpić istniejącą metodę nadklasy.
Najczęstszym przypadkiem użycia @Override są metody Object :
1 2 3 4 |
@ Override public int hashValue ( ) { System . out . Println ( "This method is using @Override Annotation" ) ; } |
Głównym powodem powstania @Override było radzenie sobie z prostymi błędami typograficznymi .
Na przykład metoda błędnie zadeklarowana jako
1 |
public int hashvalue ( ) { . . . } |
w rzeczywistości nie jest nadpisaniem — nazwa metody zawiera wszystkie małe litery, więc nie jest dokładnie taka sama jak nazwa metody hashValue() . Jednak skompiluje się doskonale. Taki błąd jest łatwy do popełnienia i trudny do wyłapania, co jest niebezpieczną kombinacją. Użycie adnotacji @Override zapobiega popełnianiu takich błędów.
Powinieneś mieć zwyczaj używania @Override za każdym razem, gdy nadpisujesz metodę nadklasy.

2) @Wycofana adnotacja:
Ta adnotacja wskazuje, że zaznaczony element jest przestarzały i nie powinien być już używany. Kompilator generuje ostrzeżenie za każdym razem, gdy program używa metody, klasy lub pola z adnotacją @Deprecated
.
Gdy element jest przestarzały, należy go również udokumentować za pomocą tagu Javadoc @deprecated
, jak pokazano w poniższym przykładzie.
1 2 3 4 |
< strong > @ Deprecated < / strong > static void deprecatedMethod ( ) { System . out . Println ( "This method is Deprecated.." ) ; } |
3) Adnotacja @SuppressWarnings:
Po prostu powiedz kompilatorowi, proszę nie krzycz. Wiem co robię .
1 2 3 4 |
@ SuppressWarnings ( "serial" ) public class OldCode implements Serializable { System . out . Println ( "This is Old Code.." ) ; } |
4) Adnotacja @Retention:
Adnotacja dotycząca przechowywania wskazuje, gdzie i jak długo mają być przechowywane adnotacje tego typu.
Istnieją trzy wartości:
- RetentionPolicy.SOURCE — adnotacje tego typu będą zachowywane tylko na poziomie źródłowym i zostaną zignorowane przez kompilator.
- RetentionPolicy.CLASS — adnotacje tego typu zostaną zachowane przez kompilator w czasie kompilacji, ale zostaną zignorowane przez maszynę wirtualną.
- RetentionPolicy.RUNTIME — adnotacje tego typu będą zachowywane przez maszynę wirtualną, dzięki czemu będą mogły być odczytywane tylko w czasie wykonywania.
1 2 3 4 |
@ Retention ( RetentionPolicy . RUNTIME ) public @ interface Crunchify_Retention { String returnSomething ( ) ; } |
5) @Udokumentowana adnotacja:
1 2 3 4 |
@ Documented public @ interface Crunchify_Documented { String writeDocument ( ) ; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class DocumentedAnnotations { public static void main ( String arg [ ] ) { new DocumentedAnnotations ( ) . performRetention ( ) ; new DocumentedAnnotations ( ) . performDocumented ( ) ; } @ Crunchify_Retention ( returnSomething = "Hello retention test" ) public void performRetention ( ) { System . out . printf ( "Testing annotation 'Crunchify_Retention'" ) ; } @ Crunchify_Documented ( writeDocument = "Hello document" ) public void performDocumented ( ) { System . out . printf ( "Testing annotation 'Crunchify_Documented'" ) ; } } |
Teraz spróbuj uruchomić polecenie Java Doc i zobacz dane wyjściowe.

6) Adnotacja @Target:
Cel wskazuje, które elementy programu mogą być opisywane przy użyciu wystąpień typu adnotacji z adnotacjami. Wartość Target jest jednym z elementów wyliczenia java.lang.annotation.ElementType
:
- ANNOTATION_TYPE. Typ adnotacji z adnotacjami może służyć do opisywania deklaracji typu adnotacji.
- KONSTRUKTOR. Adnotowany typ adnotacji może służyć do opisywania deklaracji konstruktora.
- POLE. Typ adnotacji z adnotacjami może służyć do opisywania deklaracji pola.
- LOCAL_VARIABLE. Adnotowany typ adnotacji może być użyty do adnotacji deklaracji zmiennej lokalnej.
- METODA. Adnotowany typ adnotacji może służyć do opisywania deklaracji metody.
- PAKIET. Typ adnotacji z adnotacjami może służyć do opisywania deklaracji pakietów.
- PARAMETR. Typ adnotacji z adnotacjami może służyć do opisywania deklaracji parametrów.
- RODZAJ. Typ adnotacji z adnotacjami może służyć do opisywania deklaracji typu.
1 2 3 4 |
@ Target ( value = METHOD ) You can have multiple values in the Target annotation . @ Target ( value = { TYPE , FIELD , METHOD , PARAMETER , CONSTRUCTOR , LOCAL_VARIABLE } ) |
7) @Adnotacja dziedziczona:
Dokładnie tak, jak brzmi nazwa, typ adnotacji @Inherited
jest dziedziczony przez podklasy typu adnotacji.
1 2 3 4 5 6 7 8 9 10 |
@ Inherited @ interface ForEveryone { } @ interface JustForMe { } @ ForEveryone @ JustForMe class Superclass { } class Subclass extends Superclass { } |
W tym przykładzie Superclass
został wyraźnie oznaczony @ForEveryone
i @JustForMe
. Subclass
nie została wyraźnie oznaczona żadną z nich; jednak dziedziczy @ForEveryone
, ponieważ ten ostatni jest oznaczony adnotacją @Inherited
.
@JustForMe
nie jest opatrzony adnotacjami, więc nie jest dziedziczony przez Subclass
.
Oto adnotacje na poziomie klasy
