跳转至

注解

一、概述

​ 注解(Annotation)就是代码里的特殊标记,这些标记可以在编译,类加载、运行时被读取,并执行相应的处理。通过 Annotation ,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。

​ Annotation 可以像修饰符一样被使用,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明,这些信息被保存在 Annotation 的name=value对中。

使用示例:

  1. 生成文档相关的注解
  2. 在编译时进行格式检查(JDK内置的三个基本注解)
  3. 跟踪代码依赖性,实现代替配置文件的功能

二、常见注解

1
2
3
@Override  // 编译时校验是不是重写了父类的方法
@Deprecated // 所标注内容,不再被建议使用。
@SuppressWarnings // 抑制编译器警告

三、自定义注解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class AnnotationTest {
    public static void main(String[] args) {

    }
}


//1. 注解声明为@interface
//2. 内部定义成员,通常使用value表示
//3. 可以指定成员的默认值,使用default定义
//4. 如果自定义注解没有成员,表明是一个标识作用
//5. 如果注解有成员,在使用注解时,需要指明成员的值
// 自定义注解必须配上注解的信息处理流程(使用反射才有意义)
@interface MyAnnotation {
    String value() default "hello";
}

@MyAnnotation(value = "Hi")
class Person {

    String name;
    int age;
}

四、元注解

元注解用于修饰其他元注解。JDK5.0提供了4个标准的元注解。

1. @Documented

用于指定被该元Annotation修饰的Annotation类将被javadoc工具提取成文档。默认情况下javadoc是不包括注解的。

2. @Inherited

被它修饰的Annotation将具有继承性。如果某个类使用了被@Inherited修饰的Annotation,则子类将自动具有该注解。

3. @Retention

指明Annotation的生命周期,使用时必须为该value成员变量指定值。

RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注解

RetentionPolicy.CLASS:在class文件中有效(即class保留),当运行Java程序时,JVM不会保留注解,这是默认值。

RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行Java程序时,JVM会保留注释,程序可以==通过反射获取==该注释。

4. @Target

用于指定被修饰的Annotation能用于修饰哪些程序元素。

1
2
3
4
5
6
// 指明SuppressWarnings这个注解只能用在TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE这些类型上。
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

五、JDK8中注解的新特性

1. 可重复注解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class AnnotationTest {
    public static void main(String[] args) {
    }
}

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotations {
    MyAnnotation[] value();
}

// MyAnnotation上声明Repeatable,成员值为MyAnnotations.class
@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
    String value() default "hello";
}


@MyAnnotation(value = "Hi")
class Person {
    String name;
    int age;
}

2. 类型注解

ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中(如:泛型声明)。

ElementType.YTPE_USED表示该注解能写在使用类型的任何语句中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.lang.annotation.*;
import java.util.ArrayList;

public class AnnotationTest {
    public static void main(String[] args) {
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
@interface MyAnnotations {
    MyAnnotation[] value();
}

@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
@interface MyAnnotation {
    String value() default "hello";
}


class Generic<@MyAnnotation T> {
    public void bar() throws @MyAnnotation RuntimeException{
        ArrayList<@MyAnnotation String> list = new ArrayList<>();
        int num = (@MyAnnotation int) 10;
    }
}