Annotation接口的实现类: Documented, Inherited, Retention, Target 都是用来定义自己定义的Annotation类的。
1. 注解(Annotation)类,以@interface 修饰 ,不能显示(explicit)extends或implements任何类
如:
- public @interface DefineAnnotation {
- }
这种没有任何属性的Annotation类,也叫标识Annotation
2. 定义属性
- //属性必须加个小括号
- public String value() ;
- //有默认值的属性
- public String value() default "aaa";
完整定义如下:
- //注解Annotation类不能显示(explicit)extends或implements任何类
- //不定义任何属性就叫maket annotation
- public @interface DefineAnnotation {
- //定义一个属性,有属性的话,必须赋值,除非有默认default
- public String value() default "aaa";
- }
3.使用Annotation,有默认值的可以不用传参数,也可以传递参数。没有默认值的,必须传递参数。
如:
- public class TestAnnotation {
- // @DefineAnnotation 有默认值的第一种使用方式
- // @DefineAnnotation() 有默认值的第二种使用方式
- @DefineAnnotation("ttitfly")
- public void say(){
- System.out.println("say hello");
- }
- public static void main(String[] args){
- TestAnnotation ta = new TestAnnotation();
- ta.say();
- }
- }
4. Retention (保存)
所有的Annotation类都实现了Annotation接口
@Retention本身就是个Annotation(注解)类
它的值是个enum枚举类型的RetentionPolicy,该枚举类型RetentionPolicy有三个值RUNTIME (会被JVM加载,并可以通过反射来获得到Annotation类的信息) ,CLASS (不会被JVM加载),Source
@Retention的值标识自己定义的Annotation(注解)类 是属于哪种保存策略,将来哪个类如果使用了这个自定义的注解类,将会使用这种保存策略
如:
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- //所有的Annotation类都实现了Annotation接口
- //@Retention本身就是个Annotation(注解)类
- //它的值是个enum枚举类型的RetentionPolicy,该枚举类型RetentionPolicy有三个值RUNTIME (会被JVM加载,并可以通过反射来获得到Annotation类的信息) ,CLASS (不会被JVM加载),Source
- //@Retention的值标识自己定义的Annotation(注解)类 是属于哪种保存策略,将来哪个类如果使用了这个自定义的注解类,将会使用这种保存策略
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyAnnotation {
- String hello() default "ttitfly";
- String world();
- }
- //使用自己定义的Annotation类
- public class MyTest {
- //一个方法可以有多个注解类
- @Deprecated
- @MyAnnotation(hello="china",world="earth")
- public void say(){
- System.out.println("say hello");
- }
- }
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Method;
- public class TestMain {
- //可以通过AnnotatedElement来获得到Annotation类的信息。Method,Field等都是AnnotatedElement的实现类
- public static void main(String[] args) throws Exception {
- MyTest mt = new MyTest();
- Class clazz = MyTest.class;
- //Method method = clazz.getMethod("say", null);//因为是无参数的,所以直接写个null也可以
- Method method = clazz.getMethod("say", new Class[]{});
- method.invoke(mt, new Object[]{});
- //该方法是否使用了MyAnnotation这个注解类
- boolean isExist = method.isAnnotationPresent(MyAnnotation.class) ;
- if(isExist){
- MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
- System.out.println(annotation.hello());
- System.out.println(annotation.world());
- }
- Annotation[] annotations = method.getAnnotations();
- for( Annotation annotation : annotations ){
- //打印出这样的结果:com.yahaitt.annotation.MyAnnotation
- System.out.println(annotation.annotationType().getName());
- //不能通过getClass().getName()的方式获得了。这样获得的结果类似这样的:$Proxy3,主要原因是因为Annotation在运行时刻,是通过java的动态代理实现的,
- //每次得到一个annotation,实际上并不是得到该annotation的实例,而是得到了它的一个代理,这个代理java在命名上采用的是$Proxy1,$Proxy2...的形式,数字是按照出现的顺序来定的
- //而getClass()方法返回的是该对象运行时刻所代表的真实对象,在这里也就是代理对象了
- System.out.println(annotation.getClass().getName());
- //输出结果为:java.lang.reflect.Proxy
- System.out.println(annotation.getClass().getSuperclass().getName());
- }
- }
- }
5.继承(Inherited)
在自己定义的Annotation里加入一个@Inherited ,就标识了这个定义的Annotation是可以被继承的
- import java.lang.annotation.Inherited;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- //在自己定义的Annotation里加入一个@Inherited ,就标识了这个定义的Annotation是可以被继承的
- @Inherited
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyInherit {
- String value();
- }
- @MyInherit("test class")
- public class Parent {
- @MyInherit("test method")
- public void doSomething(){
- System.out.println("hello");
- }
- }
- public class Child extends Parent{
- }
- import java.lang.reflect.Method;
- public class TestInherit {
- public static void main(String[] args) throws Exception{
- // Class< Parent > clazz = Parent.class;
- Class< Child > clazz = Child.class;
- if(clazz.isAnnotationPresent(MyInherit.class)){
- MyInherit myInherit = clazz.getAnnotation(MyInherit.class);
- System.out.println(myInherit.value());
- }
- Method method = clazz.getMethod("doSomething", new Class[]{});
- if(method.isAnnotationPresent(MyInherit.class)){
- MyInherit myInherit = method.getAnnotation(MyInherit.class);
- System.out.println(myInherit.value());
- }
- }
- }
输出结果为:
test class
test method
也就是说已经被继承了 。但是在方法上使用的Annotation也被继承了,这点有点不太明白,和文档有点冲突。