Java 使用反射处理注解
自定义注解的格式:
[public|final] @interface 注解名//@interface 表明:这是一个自定义注解
{注解元素//注解元素 是无参数的方法
}// 注解元素的格式:
数据类型 注解元素名() [default 默认值]
例子:
//自定义注解:
package test;import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
//注解作用于类和方法的声明上
@Retention(RetentionPolicy.RUNTIME)
//注解在运行时有效
public @interface UseAnno {String value() default "user";
}//使用自定义注解UseAnno
package test;
@UseAnno//在类上使用注解
public class AnnoC {@UseAnno("注解作用在方法上")//在方法上使用注解public void method() {System.out.println("在方法上使用注解");}
}
使用反射处理注解
利用反射可以在运行时动态获取类的相关信息,如类的方法、属性、构造方法。还可以创建对象、调用方法等。利用反射也可以获取注解的相关信息。
反射是在运行时获取相关信息的,要使用反射获取注解的相关信息,这个注解必须是用@Retention(RetentionPolicy.RUNTIME)声明的。
java.lang.reflect.AnnotatedElement接口定义了使用反射读取注解信息的方法:
Annotation getAnnotation(Class annotationType)
//若存在该元素指定类型的注解,则返回这些注解,否则返回null。
Annotation[] getAnnotations()
//返回此元素上存在的所有注解。包括继承的
Annotation[] getDeclaredAnnotations()
//返回该元素上存在的所有注解,不包括继承的。/*对于getAnnotations()和getDeclaredAnnotations():如果没有注释直接存在于此元素上,则返回长度为零的一个数组。该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。*/
java.lang.Package.isAnnotationPresent:
public boolean isAnnotationPresent(类<? extends Annotation> annotationClass)//若指定类型的注解存在于此元素上,则返回true,否则返回false
例:
aField.isAnnotationPresent(ApplianceMaker.class)
//意思是,判断aField字段的注解是不是ApplianceMaker 类型
//自定义注解:
package test;import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
//注解作用于类和方法的声明上
@Retention(RetentionPolicy.RUNTIME)
//注解在运行时有效
public @interface UseAnno {String value() default "user";
}//使用自定义注解UseAnno
package test;
@UseAnno//在类上使用注解
public class AnnoC {@UseAnno("注解作用在方法上")//在方法上使用注解public void method() {System.out.println("在方法上使用注解");}
}
package test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
//利用反射获取注解的值
public class ReflectAnno {public static void main(String[] args) {try {Class c = Class.forName("test.AnnoC");//获取 使用注解的类 AnnoC 的Class对象cClass cUse = Class.forName("test.UseAnno");//获取 注解类UseAnno 的Class对象cUserAnnotation anno = c.getAnnotation(cUse);//获取AnnoC类上使用的cUse注解 annoif(anno != null) {UseAnno a = (UseAnno) anno;System.out.println("AnnoC类上的注解: " + a.value());}Method m = c.getDeclaredMethod("method");Annotation an = m.getAnnotation(cUse);//获取method()方法上使用的cUse注解 anif(an != null) {UseAnno a = (UseAnno) an;System.out.println("method()方法上的注释: " + a.value());}}catch(Exception e) {e.printStackTrace();}}
}
/*输出
AnnoC类上的注解: user
method()方法上的注释: 注解作用在方法上
*/
//例子2
package test;
import java.lang.annotation.*;
import java.lang.reflect.*;
@Retention(RetentionPolicy.RUNTIME) // 元注解,运行时保留注解,必须有,否则注解值读不出
@interface ApplianceMaker // 定义注解
{// 定义注解元素,都有默认值public String type() default "TV";public String id() default "001";public String maker() default "PandaTv";public String address() default "BJ";
}@Retention(RetentionPolicy.RUNTIME)
@interface ApplianceSaler // 定义注解
{public String name() default "TM";public String id() default "001";public String address() default "HK";
}@Retention(RetentionPolicy.RUNTIME)
@interface AppliancePrice // 定义注解
{// 注解元素只有一个,名为valuepublic int value() default 1200;
}class Appliance {// 为域maker 加注解,给部分元素赋值,其余用默认值// 如果注解元素都用默认值,则直接写@ApplianceMaker@ApplianceMaker(type = "电脑", id = "201")public String maker;@ApplianceSaler(name = "JD", id = "222", address = "WH")public String saler; // 域有注解@AppliancePrice(999) // 也可以写成"value=999",因为只有一个,此处只写出值即可public int price; // 域有注解public void setMaker(String m) {maker = m;}public String getMaker() {return maker;}public void setSaler(String saler) {this.saler = saler;}public String getSaler() {return saler;}public void setPrice(int price) {this.price = price;}public int getPrice() {return price;}
}public class Test {public static void main(String args[]) {System.out.println(readAnnotation(Appliance.class));}// 读注解信息private static String readAnnotation(Class aClass) {String maker = "制造商:";String saler = "销售商:";String price = "价格:";Field fields[] = aClass.getDeclaredFields(); // 获取Appliance 类的所有字段for (Field aField : fields) // 对每一个字段判断其注解的类型{// 字段的注解是ApplianceMaker 类型if (aField.isAnnotationPresent(ApplianceMaker.class)) {ApplianceMaker aMaker; // 声明一个注解变量// 调用getAnnotation()方法获得在aField 域上的注解“实例”aMaker = (ApplianceMaker) aField.getAnnotation(ApplianceMaker.class);maker += aMaker.type() + " "; // 获取type 元素的值,其余与此相同maker += aMaker.id() + " ";maker += aMaker.maker() + " ";maker += aMaker.address() + "\n";}// 字段的注解是ApplianceSaler 类型else if (aField.isAnnotationPresent(ApplianceSaler.class)) {ApplianceSaler aSaler;aSaler = (ApplianceSaler) aField.getAnnotation(ApplianceSaler.class);saler += aSaler.name() + " ";saler += aSaler.id() + " ";saler += aSaler.address() + "\n";}// 字段的注解是AppliancePrice 类型else if (aField.isAnnotationPresent(AppliancePrice.class)) {AppliancePrice thePrice;thePrice = (AppliancePrice) aField.getAnnotation(AppliancePrice.class);price += thePrice.value();}}return maker + saler + price;}
}
/*输出:
制造商:电脑 201 PandaTv BJ
销售商:JD 222 WH
价格:999
*/