包
java.lang.annotation 中包含所有定义自定义注解所需用到的原注解和接口。
接口 java.lang.annotation.
Annotation 是所有注解继承的接口,并且是自动继承,不需要定义时指定,类似于所有类都自动继承Object。
该包同时定义了四个元注解,
Documented
注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中.
Target(作用范围,方法,属性,构造方法等),
用来声明注解可以被添加在哪些类型的元素上,如类型、方法和域等。
Retention(生命范围,源代码,class,runtime)。
用来声明注解的保留策略,有CLASS、RUNTIME和SOURCE这三种,
分别表示注解保存在类文件、JVM运行时刻和源代码中。只有当声明为RUNTIME的时候,才能够在运行时刻通过反射API来获取到注解的信息。
Inherited : 在您定义注解后并使用于程序代码上时,预设上父类别中的注解并不会被继承至子类别中,
您可以在定义注解时加上java.lang.annotation.Inherited 限定的Annotation,这让您定义的Annotation型别被继承下来
1.作用
(1)生成文档。也是最常见的,常用的有@see @param @return等
(2)替代配置文件。spring 2.5以后开始基于注解开发,现在的框架基本上都用了注解减少配置文件。【spring4.x注解概述】有具体的说明。
(3)编译时进行格式检查。 如@Override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
2.自定义注解用法
(1)建一个注解@interface TestA
package com.annotationTest;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
@Target(value = {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestA {
String name();
int id() default 0;
Class<Long> gid();
}
(2)写一个类UserAnnotation 来使用@TestA
package com.annotationTest;
import java.util.ArrayList;
import java.util.List;
@TestA(name="type",gid=Long.class) //类成员注解
public class UserAnnotation {
@TestA(name="param",id=1,gid=Long.class) //类成员注解
private Integer age ;
@TestA (name="construct",id=2,gid=Long.class)//构造方法注解
public UserAnnotation() {
}
@TestA(name="public method",id=3,gid=Long.class) //类方法注解
public void functionA(){
List list = new ArrayList();
}
@TestA(name="protected method",id=4,gid=Long.class) //类方法注解
public void functionB(){
List list = new ArrayList();
}
@TestA(name="private method",id=5,gid=Long.class) //类方法注解
public void functionC(){
List list = new ArrayList();
}
}
(3)简单打印出UserAnnotation 类中所使用到的类注解
jdk反射机制
public interface AnnotatedElement {
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
Annotation[] getAnnotations();
Annotation[] getDeclaredAnnotations();
}
isAnnotationPresent:判断是否标注了指定注解
getAnnotation:获取指定注解,没有则返回null
getAnnotations:获取所有注解,包括继承自基类的,没有则返回长度为0的数组
getDeclaredAnnotations:获取自身显式标明的所有注解,没有则返回长度为0的数组
package com.annotationTest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ParseAnnotation {
public static void parseTypeAnnotation() throws ClassNotFoundException{
Class clazz = Class.forName("com.annotationTest.UserAnnotation");
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
TestA testA = (TestA) annotation;
System.out.println("id = "
+testA.id()
+"\t name = "
+testA.name()
+"\t gid = "
+testA.gid()
);
}
}
private static void parseConstructAnnotation() {
Constructor[] constructors = UserAnnotation.class.getConstructors();
for (Constructor constructor : constructors) {
boolean hasAnnotation = constructor.isAnnotationPresent(TestA.class);
if (hasAnnotation) {
TestA annotation = (TestA) constructor.getAnnotation(TestA.class);
System.out.println("constructor : "
+constructor.getName()
+"\t id = "
+annotation.id()
+"\t name = "
+annotation.name()
+"\t gid = "
+annotation.gid()
);
}
}
}
private static void parseMethodAnnotation() {
Method[] methods = UserAnnotation.class.getDeclaredMethods();
for (Method method : methods) {
/*
* 判断方法中是否有指定注解类型的注解
*/
boolean hasAnnotation = method.isAnnotationPresent(TestA.class);
if (hasAnnotation) {
TestA annotation = method.getAnnotation(TestA.class);
System.out.println("method : "
+method.getName()
+"\t id = "
+annotation.id()
+"\t name = "
+annotation.name()
+"\t gid = "
+annotation.gid()
);
}
}
}
public static void main(String[] args) throws ClassNotFoundException {
parseTypeAnnotation();
parseConstructAnnotation();
parseMethodAnnotation();
}
}
3.建议
(1) 不要滥用注解。首先强烈建议学习好框架里出现的注解,按照框架规定的方式使用。
(2) 不要滥用注解。平常我们编程过程很少接触和使用注解,只有做设计,且不想让设计有过多的配置时。
(3) 要用好注解,必须熟悉java 的反射机制,从上面的例子可以看出,注解的解析完全依赖于反射。