Kurs Java Podstawy - rozszerzony

Własne adnotacje. Definiowanie i zastosowanie.

Historia zmian

[table tablesorter="1" ]

Data,Opis

14.01.2014,Dodanie artykułu

[/table]

Co to są adnotacje?

Najłatwiej będzie zacząć od fragmentu kodu. Adnotacje zaczynają się od znaku małpy @, następnie podawana jest nazwa klasy. Poprzedza się nimi deklaracje pakietów, klas, pól i metod.

@DatabaseTable(tableName = "notes")
public class Note {

	@DatabaseField(id = true, columnName = "date")
	private long date;

	@DatabaseField(columnName = "text")
	private String text;
}

 

Adnotacje zostały dodane wraz z Java 5. Często spotykane w bibliotekach ORM, a także w JUnitach. Służą do wygodnego ustawiania własności. Powyższy fragment pochodzi z mojego projektu na platformę Android, korzystającej z biblioteki OrmLite. Ten fragment kodu wystarcza by wygenerować w bazie danych tabelę o nazwie "notes" z dwoma kolumnami: "date" i "text", gdzie "date" to klucz podstawowy (uprzedzając pytania: tak, zdaję sobie sprawę, że ustawianie daty jako klucza jest dziwne :))

Jak zdefiniować własną adnotację?

 

Definiowanie własnej adnotacji jest bardzo proste.

@Target({ ElementType.FIELD })
public @interface DatabaseField {

}

 

Ciężko było mi wymyślić jakiś kreatywny przykład, więc spróbujemy zreplikować kod z przykładu. Zdefiniowaniu takiej adnotacji możemy jej użyć w kodzie:

 

public class User {

	@DatabaseField
	private String name;

}

 

Nowością jest linia zawierająca: @Target({ ElementType.FIELD }). Oznacza to ograniczenia, że tę adnotację możemy zastosować jedynie do pól. Oto lista dostępnych ograniczeń:

  • ElementType.ANNOTATION_TYPE
  • ElementType.CONSTRUCTOR
  • ElementType.FIELD
  • ElementType.LOCAL_VARIABLE
  • ElementType.METHOD
  • ElementType.PACKAGE
  • ElementType.PARAMETER
  • ElementType.TYPE

Wpisujemy je bezpośrednio przed deklaracją, jak w przykładzie powyżej. W celu zastosowania kilku możliwych typów wpisujemy je po przecinku np: @Target({ ElementType.FIELD, ElementType.METHOD })

 

Parametry dla adnotacji

W celu umożliwienia dodania parametrów dla adnotacji należy stworzyć metody o odpowiadającej nazwie i zwracające typ parametru:

@Target({ ElementType.FIELD })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface DatabaseField {

	String columnName();

}

 

Zauważcie, że dodałem także: @Retention(value = RetentionPolicy.RUNTIME). Oznacza to tyle, że adnotacje będą wykrywane w czasie wykonywania programu.

Jak użyć adnotacji?

 

Do tej pory nie było nic skomplikowanego. No, ale dopiero teraz zaczyna robić się ciekawie. Celem skorzystania z adnotacji musimy użyć refleksji (tutaj chciałem wstawić link do artykułu opisującego ten mechanizm, ale najwidoczniej jeszcze takiego nie mamy. Dopisuję na moją TODO listę ;))

Refleksja umożliwia na przeglądanie i ewentualną edycję działania aplikacji w czasie trwania jej działania. Korzystając z niej możemy m.in.: pobrać listę pól zadeklarowanych w klasie, razem z ich wartościami i ich zamianę nawet jeśli są to pola prywatne. Tyle w skrócie. Po więcej informacji zapraszam do oficjalnego tutorialu [ANG].

 

public class Main {

	public static void main(String[] args) {
		Main main = new Main();
		main.run();
	}

	public void run() {
		User user = new User();

		Field[] fields = user.getClass().getDeclaredFields();

		for (Field field : fields) {
			if(field.isAnnotationPresent(DatabaseField.class)) {
				DatabaseField databaseField = field.getAnnotation(DatabaseField.class);
				System.out.println("Field name: "+field.getName() + " | Column name: " + databaseField.columnName());
			}
		}
	}

}

 

W powyższym fragmencie pokazuję jak możemy użyć naszych adnotacji. Zaczynamy od utworzenia instancji klasy User. Następnie pobieramy wszystkie jej pola korzystając z getDeclaredFields(). Tutaj pragnę zaznaczyć, że ta metoda zwraca także pola prywatne. Jeśli takowe nas nie interesują to możemy skorzystać z getFields(). Później tylko iterujemy po każdym polu, sprawdzamy czy jest to obiekt oznaczony interesującą nas adnotacją, a jeśli tak to odpowiednio go obsługujemy. Ograniczam się tylko do wyświetlenia wartości adnotacji, ale równie dobrze mógłbym stworzyć tutaj zapytanie do bazy danych tworzące odpowiednią kolumnę.

 

Kod źródłowy

 

Pełny i aktualny kod źródłowy programu dostępny jest na GitHubie pod adresem: https://github.com/javastartpl/annotations. Jeśli nie macie doświadczenia z git, to na dole po prawej dostępna jest opcja "Download ZIP" pozwalająca pobrać cały projekt.

Podsumowanie

 

Osobiście długo zwlekałem zanim przyjrzałem się temu mechanizmowi. Moim zdaniem ciężko znaleźć dla niego zastosowanie w codziennych projektach, ale zdecydowanie warto go poznać. Jednym z ciekawszych projektów które go wykorzystują na wysoką skalę to AndroidAnnotations.

Opisałem tylko część możliwości. Jeśli wyrazicie takie zainteresowanie, to mogę spróbować przyjrzeć się także innym aspektom.

Co sądzicie o adnotacjach? Może wykorzystaliście je kiedyś we własnych projektach, a może sprawiają one Wam kłopoty? Zapraszam do dyskusji w komentarzach :)

Komentarze

Lolo

Szkoda, że strona została trochę zaniedbana i tak samo forum, bo miały moim zdaniem potencjał. A teraz już chyba trochę straciły.

Tomek

Jestem podobnego zdania. Mam nadzieję, że ten comeback się wydarzy. Trzymam kciuki

Marcin Kunert

Nic się nie bój. Jeszcze będzie comeback :)

Lolo

Proponuję założyć jakieś antyBotowe zabezpieczenie na forum, bo ostatnio jak tam byłem to było pełno spamu. Chyba, że już to zrobiliście.

Proponuję również jakiś newsletter zrobić, żeby były powiadomienia o nowych artykułach.

Marcin Kunert

Dostępny jest kanał RSS, a forum będzie trzeba się przyjrzeć.

WsC

Ja również czekam na nowe materiały.Mam nadzieję że wkrótce pojawią się nowe materiały.
Pozdrawiam.