首页 java基础-注解
文章
取消

java基础-注解

注解

  在Java中,注解其实就是一种元数据标记,用于在类、方法、字段或其他程序元素前添加特殊标记。注解提供了丰富的方式在Java代码中添加元数据,这些元数据可以在编译时进行检查,也可以在运行时通过反射机制处理。

  注解本身是一个特殊的接口,通常继承自 java.lang.annotation 包中的 Annotation 接口。这些接口的定义是元数据的“形状”,定义了注解可以包含的数据结构。

  注解包括系统注解和自定义注解,系统注解如 @Override@Deprecated 是Java内置的,用于提供特定的功能,如标识方法覆盖或标记过时的方法。也可以自定义注解,比如spring框架就自定义了大量注解。

  注解本身就是一个标记,而提供的功能是要看如何处理。这就像这篇文章,添加了一些tags,这些tags被系统实现为快速搜索。也可以添加一些其他的标签然后自定义一个处理方法,比如用于排序。所有关键还是如何处理。

  注解的处理主要有两种方式:

  • 编译期间通过继承AbstractProcessor并实现processor方法

  • 运行时通过反射来处理。

元注解

  简单来说,元注解就是用来标记注解的。在定义注解时,必须使用元注解 @Retention@Target@Inherited@Documented 说明注解的作用域、使用范围、是否可继承和是否输出到 API 文档中。

1
2
3
4
5
6
7
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Target(ElementType.TYPE)
@Documented
public @interface MyAnnotation {
    String name() default "default";
}
  • @Retention:表示保留期,它的值定义了该注解的生命周期。
  • @Target:表示适用范围,可以指定作用在注解上的目标元素类型,如类、方法、成员变量等。多个目标类型可以用逗号隔开,如果省略该元素,表示定义的注解可以用在所有的程序元素上。
  • @Inherited:表示注解可以被继承,默认情况下,注解不会被继承。如果注解需要被子类继承,可以在定义注解时使用 @Inherited 元注解。
  • @Documented:表示注解中的元素可以被 javadoc 工具读取并生成文档。

@Retention

   @Retention 用来指定注解的生命周期(源码、class文件、运行时),其可选值如下:

  • RetentionPolicy.SOURCE : 注解只存在于编译器处理期间,在编译阶段丢弃,不会在编译输出的 class 文件中出现。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。适用于限制程序员编写代码时使用的注解。@Override, @SuppressWarnings都属于这类注解。
  • RetentionPolicy.CLASS : 注解会被编译器记录在 class 文件中,但是在运行时 JVM 不会保留,在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
  • RetentionPolicy.RUNTIME : 注解会被编译器记录在 class 文件中,始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。

@Target

   @Target 注解指定了注解可以被用来修饰哪些程序元素,例如类、方法、域等。@Target 的取值类型有以下常量:

  • ElementType.TYPE:用于标注类、接口、枚举。
  • ElementType.CONSTRUCTOR:用于标注构造方法。
  • ElementType.FIELD:用于标注成员变量。
  • ElementType.METHOD:用于标注方法。
  • ElementType.PARAMETER:用于标注参数。
  • ElementType.LOCAL_VARIABLE:用于标注局部变量。
  • ElementType.ANNOTATION_TYPE:用于标注注解。
  • ElementType.PACKAGE:用于标注包。

@Inherited

   @Inherited 注解表示标注了此注解的类的子类也会被标注此注解,即:允许子类继承父类注释。

@Documented

   @Documented 注解也被称为文档化注解,加上这个注解后,注解的信息就可以被 javadoc 所解析。

定义注解

1
2
3
4
5
6
7
8
9
10
11
12
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface MyAnnotation {

    // 有默认值
    int id() default 0;

    // 没有默认值
    String value();
}

  上面定义一个注解,运行时有效,可以用于方法和成员变量上,允许继承,并可以通过javadoc解析。

使用并处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 使用注解
public class Hello {

    @MyAnnotation(id=1,value="mmy83")
    private String name;

    @MyAnnotation(id=2,value="mmy83@126.com")
    private String email;

    @MyAnnotation(id=3,value="hello")
    public void say(){
        System.out.println(name);
    }

    @MyAnnotation("word")
    public void helloword(){
        System.out.println(name);
    }
}

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 处理
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Main {

    public static void main(String[] args) {
        try {
            //获取所有的类成员变量
            Field[] fields = Hello.class.getDeclaredFields();
            for (Field field : fields) {
                //类成员变量
                String fieldName = field.getName();
                //注解
                Annotation[] fieldAnnotations = field.getAnnotations();
                for (Annotation annotation : fieldAnnotations) {
                    Class<? extends Annotation> annotationType = annotation.annotationType();
                    String annotationSimpleName = annotationType.getSimpleName();
                    if (annotationType.equals(MyAnnotation.class)) {
                        MyAnnotation myAnnotation = field.getAnnotation(MyAnnotation.class);
                        System.out.printf(" 成员变量: %s, 注解:%s, id: %d, value: %s \n" ,fieldName, annotationSimpleName,myAnnotation.id(),myAnnotation.value());
                    }
                }
            }
            //反射遍历所有方法
            Method[] methods = Hello.class.getDeclaredMethods();
            for (Method method : methods) {
                String methodName = method.getName();
                Annotation[] methodAnnotations = method.getAnnotations();
                for(Annotation annotation : methodAnnotations) {
                    Class<? extends Annotation> annotationType = annotation.annotationType();
                    String annotationSimpleName = annotationType.getSimpleName();
                    if (annotationType.equals(MyAnnotation.class)) {
                        MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
                        System.out.printf(" 成员方法: %s, 注解:%s, id: %d, value: %s \n" ,methodName, annotationSimpleName,myAnnotation.id(),myAnnotation.value());
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

1
2
3
4
 成员变量: name, 注解:MyAnnotation, id: 1, value: mmy83 
 成员变量: email, 注解:MyAnnotation, id: 2, value: mmy83@126.com 
 成员方法: helloword, 注解:MyAnnotation, id: 0, value: word 
 成员方法: say, 注解:MyAnnotation, id: 3, value: hello 

注: 反射方式处理要求

@Retention(RetentionPolicy.RUNTIME)

本文由作者按照 CC BY 4.0 进行授权

Linux虚拟化-LVM扩容

再谈写博客