Java笔记5-注解

目录

  • 使用注解
  • 定义注解
  • 处理注解

笔记摘自 廖雪峰的官方网站-Java教程-注解 。

使用注解

注解(Annotation)是放在Java源码的类、方法、字段、参数前的一种特殊“注释”。

// this is a component:
@Resource("hello")
public class Hello {
    @Inject
    int n;

    @PostConstruct
    public void hello(@Param String name) {
        System.out.println(name);
    }

    @Override
    public String toString() {
        return "Hello";
    }
}

Java的注解可以分为三类:

  • 第一类是由编译器使用的注解,例如:
@Override:让编译器检查该方法是否正确地实现了覆写;
@SuppressWarnings:告诉编译器忽略此处代码产生的警告。
这类注解不会被编译进入.class文件,它们在编译后就被编译器扔掉了。
  • 第二类是由工具处理.class文件使用的注解,比如有些工具会在加载class的时候,对class做动态修改,实现一些特殊的功能。这类注解会被编译进入.class文件,但加载结束后并不会存在于内存中。这类注解只被一些底层库使用,一般我们不必自己处理。
  • 第三类是在程序运行期能够读取的注解,它们在加载后一直存在于JVM中,这也是最常用的注解。例如,一个配置了@PostConstruct的方法会在调用构造方法后自动被调用(这是Java代码读取该注解实现的功能,JVM并不会识别该注解)。

定义一个注解时,还可以定义配置参数,没有指定配置的参数使用默认值。配置参数可以包括:

  • 所有基本类型;
  • String;
  • 枚举类型;
  • 基本类型、String、Class以及枚举的数组;
  • Class类型和其数组。

因为配置参数必须是常量,所以,上述限制保证了注解在定义时就已经确定了每个参数的值。

public class Hello {
    @Check(min=0, max=100, value=55)
    public int n;

    @Check(value=99)
    public int p;

    @Check(99) // 相当于 @Check(value=99)
    public int x;

    @Check // 所有参数都使用默认值
    public int y;
}

定义注解

Java使用@interface定义注解:

可定义多个参数和默认值,核心参数使用value名称;

必须设置@Target来指定Annotation可以应用的范围;

应当设置@Retention(RetentionPolicy.RUNTIME)便于运行期读取该Annotation

注解的参数类似无参数方法,可以用default设定一个默认值(强烈推荐)。最常用的参数应当命名为value。

public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

元注解
有一些注解可以修饰其他注解,这些注解就称为元注解(meta annotation)。

@Target
最常用的元注解是@Target。使用 @Target 可以定义 被定义的注解Annotation 能够被应用于源码的以下这些位置:

  • 类或接口:ElementType.TYPE;
  • 字段:ElementType.FIELD;
  • 方法:ElementType.METHOD;
  • 构造方法:ElementType.CONSTRUCTOR;
  • 方法参数:ElementType.PARAMETER。

例如,定义注解@Report可用在方法上,我们必须添加一个@Target(ElementType.METHOD):

@Target(ElementType.METHOD)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

定义注解@Report可用在方法或字段上,可以把@Target注解参数变为数组{ ElementType.METHOD, ElementType.FIELD }:

@Target({
    ElementType.METHOD,
    ElementType.FIELD
})
public @interface Report {
    ...
}

@Retention
另一个重要的元注解@Retention定义了Annotation的生命周期:

  • 仅编译期:RetentionPolicy.SOURCE;
  • 仅class文件:RetentionPolicy.CLASS;
  • 运行期:RetentionPolicy.RUNTIME。

如果@Retention不存在,则该Annotation默认为CLASS。通常定义为 RUNTIME 。

@Repeatable
使用@Repeatable这个元注解可以定义Annotation是否可重复。这个注解应用不是特别广泛。
详情见 @Repeatable 。

@Inherited
使用@Inherited定义子类是否可继承父类定义的Annotation。@Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效,并且仅针对class的继承,对interface的继承无效。

总结 如何定义Annotation
第一步,用@interface定义注解;
第二步,添加参数、默认值:把最常用的参数定义为value(),推荐所有参数都尽量设置默认值;
第三步,用元注解配置注解,其中,必须设置@Target和@Retention,@Retention一般设置为RUNTIME,因为我们自定义的注解通常要求在运行期读取。一般情况下,不必写@Inherited和@Repeatable。

处理注解

可以在运行期通过反射读取RUNTIME类型的注解,注意千万不要漏写@Retention(RetentionPolicy.RUNTIME),否则运行期无法读取到该注解。

可以通过程序处理注解来实现相应的功能:

  • 对JavaBean的属性值按规则进行检查;
  • JUnit会自动运行@Test标记的测试方法。

有点琐碎,要用的时候再看,详情见 处理注解 。
注意阅读网站原文的评论,会有收获。

你可能感兴趣的:(java,java)