Java注解的学习和总结
以前没写过多少java对java的注解模式很好奇,今天就凑空研究一下看一下。
1. Java元注解
元注解包括四种@Retention @Target @Document @Inherited这四种注解。
- Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口。
- 参数成员只能用public或者default这两种访问权限修饰。
- 参数成员只能用byte、String等基础类型。
- 要获取类方法和字段的注解信息,必须通过Java的反射技术来获取Annotation对象,因为你除此之外没有别的获取注解对象的方法。
自定义注解类的时候可以指定目标(类、方法、字段, 构造函数等)、注册的生命周期,是否将注解包含javadoc中及是否允许子类继承父类中的注解, 具体如下:
- @Target 表示该注解目标,可能的 ElemenetType 参数包括:
ElemenetType.CONSTRUCTOR 构造器声明 ElemenetType.FIELD 域声明(包括 enum 实例) ElemenetType.LOCAL_VARIABLE 局部变量声明 ElemenetType.METHOD 方法声明 ElemenetType.PACKAGE 包声明 ElemenetType.PARAMETER 参数声明 ElemenetType.TYPE 类,接口(包括注解类型)或enum声明
- @Retention 表示该注解的生命周期,可选的 RetentionPolicy 参数包括:
RetentionPolicy.SOURCE 注解将被编译器丢弃
RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃
RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息
- @Documented 指示将此注解包含在 javadoc 中.
- @Inherited 指示允许子类继承父类中的注解.
2.类注解
注解实例
@MyAnnotation(name="someName", value = "Hello World")
public class TheClass {
}
上面就是实际中使用注解的例子。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
public String name();
public String value();
}
上面是一个定义注解的例子。 下面是使用一个注解:
Class aClass = TheClass.class;
Annotation[] annotations = aClass.getAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
}
另外一种使用方法:
Class aClass = TheClass.class;
Annotation annotation = aClass.getAnnotation(MyAnnotation.class);
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
3. 方法注解
方法注解
public class TheClass {
@MyAnnotation(name="someName", value = "Hello World")
public void doSomething(){}
}
可以用下面的方法来使用:
Method method = ... // 获取方法对象
Annotation annotation = method.getAnnotation(MyAnnotation.class);
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
4. 参数注解
也可以使用参数注解
public class TheClass {
public static void doSomethingElse(
@MyAnnotation(name="aName", value="aValue") String parameter){
}
}
下面是注解模式的应用
Method method = ... //获取方法对象
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Class[] parameterTypes = method.getParameterTypes();
int i=0;
for(Annotation[] annotations : parameterAnnotations){
Class parameterType = parameterTypes[i++];
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("param: " + parameterType.getName());
System.out.println("name : " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
}
}
5. 变量注解
变量注解例子:
public class TheClass {
@MyAnnotation(name="someName", value = "Hello World")
public String myField = null;
}
访问指定变量的注解:
Field field = ... //获取方法对象
Annotation[] annotations = field.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
}
总结
注解可以在运行时候使用java的反射来进行动态的处理,也可以在java编译阶段进行处理。