Java注解类型(@Annotation)

简述

注解本质是一个继承了 Annotation 的特殊接口,其具体实现类是 Java 运行时生成的动态代理类。而我们通过反射获取注解时,返回的是 Java 运行时生成的动态代理对象 $Proxy1。通过代理对象调用自定义注解(接口)的方法,会最终调用 AnnotationInvocationHandler 的 invoke 方法。该方法会从 memberValues 这个 Map 中索引出对应的值。而 memberValues 的来源是 Java 常量池。

实际上 Java 注解与普通修饰符 (public、static、void 等) 的使用方式并没有多大区别,下面的例子是常见的注解:

 1 public class AnnotationDemo {
 2    
 3    @Test
 4    public static void A(){
 5        System.out.println("Test.....");
 6    }
 7    @Deprecated
 8    @SuppressWarnings("uncheck")
 9    public static void B(){
10  
11    }
12 }

 

基本语法

使用 Annotation 时要在其前面增加 @ 符号, 并把该 Annotation 当成一个修饰符使用.

用于修饰它支持的程序元素 三个基本的 Annotation:

  • @Override: 限定重写父类方法, 该注释只能用于方法
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {}

 

  • @Deprecated: 用于表示某个程序元素 (类, 方法等) 已过时
@Documented@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {}

 

  • @SuppressWarnings: 抑制编译器警告.
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {String[] value();}

 

 

注解的应用结构图

 

注解不支持继承

注解是不支持继承的,因此不能使用关键字 extends 来继承某个 @interface,但注解在编译后,编译器会自动继承 java.lang.annotation.Annotation 接口,这里我们反编译前面定义的 DBTable 注解:

package com.zejian.annotationdemo;
import java.lang.annotation.Annotation;
public interface DBTable extends Annotation{
   public abstract String name();}

 

虽然反编译后发现 DBTable 注解继承了 Annotation 接口,请记住,即使 Java 的接口可以实现多继承,但定义注解时依然无法使用 extends 关键字继承 @interface。

 

为注解增加高级属性

  • 数组类型的属性
  1. int [] arrayAttr() default {1,2,3};
  2. @MyAnnotation(arrayAttr={2,3,4})
  3. 如果数组属性中只有一个元素,这时候属性值部分可以省略大括
  • 枚举类型的属性
  1. EnumTest.TrafficLamp lamp() ;
  2. @MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
  • 注解类型的属性:
  1. MetaAnnotation annotationAttr() default
  2. @MetaAnnotation("xxxx"); @MyAnnotation(annotationAttr=@MetaAnnotation(“yyy”) )
  3. 可以认为上面这个 @MyAnnotation 是 MyAnnotaion 类的一个实例对象,同样的道理,可以认为上面这个 @MetaAnnotation 是 MetaAnnotation 类的一个实例对象,调用代码如下:

      MetaAnnotation ma = myAnnotation.annotationAttr();

      System.out.println(ma.value());

  • 注解的详细语法可以通过看 java 语言规范了解,即看 java 的 language specification。

心得:

    只有脚踏实地的人,才能够说:“路” 就在我脚下。