首先新建一个注解(Annotation),可以直接在Eclipse右键->new->Annotation。在创建界面,我们会看到一些可选项,分别为:Retention、Target、Inherited、Documented。
@Retention
字面意思保留,保持。按照其字面意思很容易理解,也可以理解为生命周期,有三个分类,或者说三个等级:
(1)source:源码级注解。意思是该注解只在源码种存在,编译成class文件就不存在了。
(2)class:编译时注解。意思是在源码及编译后的class文件中均存在。
(3)runtime:运行时注解。在程序运行阶段还会起作用,甚至会对运行逻辑起作用的注解,可以通过反射读取。
@Target
注解的作用域。范围很大,在新建注解时可以看到有以下条目:

@Inherited
允许子类继承。是一个标识性的元注解(元注解:给注解进行注解的注解,叫做元注解。)。
@Documented
生成JavaDoc的时候会包含注解的相关信息,也属于元注解。
新建Description注解:Description.java
package org.devsong.test;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target({ TYPE, METHOD })
@Inherited
@Documented
public @interface Description {
String value();
}
成员变量以无参无异常的方式声明,可以用default为成员指定一个默认值,例如,一个名为count的成员,默认值为10: int count() default 10。成员的类型是受限制的,合法的类型包括原始类型及String,Class,Annotation,Enumeration。当注解只有一个成员的时候,成员名应为value,在赋值时可以忽略成员名和赋值符号(=)。下面新建测试类及测试目标类(简单演示,建在了一个文件中):ParseAnnotation.java
package org.devsong.test;
import java.lang.reflect.Method;
public class ParseAnnotation {
public static void main(String[] args) {
try {
//使用类加载器加载类
Class c = Class.forName("org.devsong.test.Foo");
System.out.println("==========开始解析类注解==========");
if(c.isAnnotationPresent(Description.class)) {
//获取注解实例
Description desc = (Description) c.getAnnotation(Description.class);
//获取注解成员值并输出
System.out.println(desc.value());
}
System.out.println("==========开始解析方法注解==========");
Method[] methods = c.getMethods();
//遍历所有的方法
for(Method m : methods) {
if(m.isAnnotationPresent(Description.class)) {
Description desc = (Description) m.getAnnotation(Description.class);
System.out.println(desc.value());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
//测试目标类
@Description("class annotation")
class Foo{
@Description("method annotation 1")
public void sayHello() {
System.out.println("hello");
}
@Description("method annotation 2")
public void sayHi() {
System.out.println("hi");
}
}
运行结果如下:
==========开始解析类注解==========
class annotation
==========开始解析方法注解==========
method annotation 1
method annotation 2
当然除了上述方法之外,也可以用getAnnotations()方法获取当前类的所有注解,然后再遍历每一个注解进行处理。只有运行时注解才会被取到。
另外,用@Inherited注解了当前注解就表示当前注解允许子类继承,值得注意的是仅仅只是继承类上面的注解,而不会继承方法上的注解。也就是说下面类只从Foo类中继承了类注解(@DEscription("class annotation")),而不会继承方法注解。
//测试目标类二
//只会从Foo类中继承了类注解而不会继承方法注解
class Foo1 extends Foo{
@Override
public void sayHello() {
System.out.println("hello");
}
@Override
public void sayHi() {
System.out.println("hi");
}
}
若运行类解析对Foo1类进行注解解析,将只会得到以下结果:
==========开始解析类注解==========
class annotation
==========开始解析方法注解==========