Отримання інформації про анотації

травня
24
2012
Мітки: @retention annotation java

Зміст

Мало додати анотацію до класу, необхідно мати спосіб отримати інформацію про неї: що описує анотація (клас, метод, параметр і т.д,), якими властивостями володіє і інші характеристики. У цій статті мова піде саме про цю інформацію.

Як згадувалося в попередніх статтях, анотація має три області видимості, описувані анотацією @Retention:

Для того щоб отримати інформацію про анотації першого типу необхідно розібрати вихідний код програми. Способів це зробити існує величезна кількість, але розгляд їх виходить за межі даної статті.

При використанні анотації @Retention з типом CLASS необхідно проробити схожі дії, але розібрати не вихідний код програми, а скомпільований .class файл. Опис способу як це зробити також виходить межі цієї статті.

І, нарешті, анотація з останнім типом RUNTIME анотації @Retention. Щоб отримати інформацію про анотації класу необхідно скористатися рефлексією. Перейдемо до прикладу.

Створимо наступні дві анотації: @Mammal (ссавець) і @HasHorn (наявність рогу):


package com.seostella.annotation.def;

import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Target(ElementType.TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Mammal {
	String sound();

	int color();
}


package com.seostella.annotation.def;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HasHorn {
	int length() default 30;
}

Нагадаємо значення згаданих у прикладі анотацій:

@Target(ElementType.TYPE) - анотація може використовуватися тільки з класом, інтерфейсом, перерахуванням enum або з іншого анотацією.

@Documented - зазначаємо, що дана анотація буде вказана в згенерованій документації JavaDoc.

@Retention(RetentionPolicy.RUNTIME) - анотація зберігається в .class файлі і доступна під час виконання програми.

@Inherited - анотація автоматично успадковується в дочірніх класах описаного анотацією класу.

@Target(ElementType.METHOD) - анотація може використовуватися тільки з методом класу.

Створимо клас Giraffe, який використовує обидві анотації:


package com.seostella.annotation.domain;

import com.seostella.annotation.def.HasHorn;
import com.seostella.annotation.def.Mammal;

@Mammal(color = 0xFFA844, sound = "uuuu")
public class Giraffe {
	
	@HasHorn
	public void drawHead() {
	}
	
}

Також, щоб продемонструвати роботу анотації @Inherited, створимо клас FeatureGiraffe:


package com.seostella.annotation.domain;

public class FeatureGiraffe extends Giraffe{

}

Тепер приступимо до безпосереднього розбору анотацій. Створіть, наприклад, клас з наступним змістом:


package com.seostella.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import com.seostella.annotation.domain.FeatureGiraffe;

public class Main {
	public static void main(String[] args) {
		try {
			
			FeatureGiraffe giraffe = new FeatureGiraffe();
			Annotation[] classAnnotations = giraffe.getClass().getAnnotations();

			System.out.println( giraffe.getClass().getName() + " annotations:");
			for (Annotation annotation : classAnnotations)
				System.out.println( "  " + annotation);
			
			Method[] classMethods = giraffe.getClass().getMethods();
			System.out.println(" Method annotations:");
			for( Method method : classMethods ){
				Annotation[] methodAnnotations = method.getAnnotations();
				if( methodAnnotations.length > 0 ){
					System.out.println("  " + method.getName() + "():");
				}
				for( Annotation annotation : methodAnnotations ){
					System.out.println( "    " + annotation);
				}
			}
			
		} catch (Exception exc) {
		}
	}
}

Результатом виконання програми будуть наступні рядки:


com.seostella.annotation.domain.FeatureGiraffe annotations:
  @com.seostella.annotation.def.Mammal(color=16754756, sound=uuuu)
 Method annotations:
  drawHead():
    @com.seostella.annotation.def.HasHorn(length=30)

Як видно з прикладу, хоч в класі FeatureGiraffe і не оголошені анотації, вони успадковуються з батьківського класу Giraffe.

На цьому закінчимо серію статей про анотації. Велике спасибі за увагу! :)

< Анотації в Java. @Inherited

Напишіть перше повідомлення!

Ви повинні увійти під своїм аккаунтом щоб залишати коментарі