紫郢青索

知之者不如好之者,好之者不如乐之者

用户工具

站点工具


Java 注解 annotation

注解主要有如下几个用途

  1. 在编译阶段进行代码检测
  2. 在构建时使用完成构建时的一些动作
  3. 在运行时通过代码去读取注解,实现一些运行时的功能

注解的基本语法

使用格式如下:

@RequestMapping(value = "/go/index")

非常简单,就是@开头后面给上注解的名称,如果注解支持参数,可以在注解名字后面紧跟圆括号。在圆括号中填入属性名=属性值

Java内置的注解

@Deprecated

可以用在类、方法、属性上,表示它已不再使用了。如果你在代码中使用了,编译器将会提示一个警告信息。 可以配合Javadoc的@deprecated 给出不再使用的解释。 例如:

    /**
     * @deprecated  这个方法已经被新的方法 running() 替代,walk()不再使用了
     */
    @Deprecated
    public void walk(){
    }

@Override

使用在子类继承父类的方法上,这个不是必须要写的。建议是最好写上,防止父类的方法改写名字后,造成子类没有重写父类的方法。如果使用@Override,编译时会提示你没有复写父类的方法。 例如:

    class MySuperCar{
        public void running(){
            System.out.println("MySuperCar running");
        }
    }
 
    class MySubCar extends MySuperCar{
        @Override
        public void running(){
            System.out.println("MySubCar running");
        }
    }

@SuppressWarnings

使用在方法上可以禁止提示一些警告信息。比如方法中使用@Deprecated注解的方法,或者进行了不安全的类型转换,编译时会提示一些警告信息。使用了@SuppressWarnings可以禁止掉这些提示。 例如:

    @SuppressWarnings
    public void walk(){
    }

创建自定义注解

自定义注解实例

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Inherited
    @Documented
    public @interface MyAnnotation {
        String   value();
        String   name();
        int      age();
        String[] newNames();
    }
 

上面的代码定义了一个注解,名称为 MyAnnotation, 属性有 value, name, age, newNames。 定义中有几个关键字如下,分别解释下:

  • @interface 关键字告诉Java编译器这里定义了一个注解。
  • @Retention 指定定义的注解在哪个阶段是可用的。RetentionPolicy 有如下三个取值:
    - RUNTIME (在运行时可以获得)
    - CLASS (在.class文件中保留)
    - SOURCE (只保留在源文件中)
  • @Target指定注解可以使用的位置,有如下几个值:
    ElementType.ANNOTATION_TYPE
    ElementType.CONSTRUCTOR
    ElementType.FIELD
    ElementType.LOCAL_VARIABLE
    ElementType.METHOD
    ElementType.PACKAGE
    ElementType.PARAMETER
    ElementType.TYPE

通过字面含义就可以知道其含义,需要说明的是TYPE 表示任何位置。ANNOTATION_TYPE 表示只用在注解上。 使用了@Inherited,注解会被子类继承。 例如:

    @Inherited
    public @interface MyAnnotation {
    }
 
    @MyAnnotation
    class MySuperCar{
    public void running(){
        System.out.println("MySuperCar running");
    }
    }
 
    class MySubCar extends MySuperCar{
        @Override
        public void running(){
            System.out.println("MySubCar running");
        }
    }

子类MySubCar 也会有@MyAnnotation注解,因为父类的注解使用了@Inherited。 @Documented 告诉 JavaDoc 工具,自定义的注解也会出现在JavaDoc生成的文档中。

通过Java反射Reflect访问注解

定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Documented
public @interface MyAnnotation {
    String   value();
    String   name();
    int      age();
    String[] newNames();
}

使用注解

@MyAnnotation(
        value="123",
        name="Jim",
        age=37,
        newNames={"Jame", "Mike"}
)
public class MyAnotaionClass {
}

通过反射读取注解信息

@Slf4j
public class DemoTest {
 
    public static void main(String[] args) {
        reflectTest();
    }
 
    public static void reflectTest(){
        Class myObjClass = null;
        MyAnotaionClass myAnotaionClass = new MyAnotaionClass();
        myObjClass = myAnotaionClass.getClass();
        MyAnnotation myAnnotation = (MyAnnotation)myObjClass.getAnnotation(MyAnnotation.class);
        if(myAnnotation != null){
            log.info(myAnnotation.toString());
            String[] strings = myAnnotation.newNames();
            log.info(Arrays.toString(strings));
        }
    }
}