Java学习笔记——新特性-注解

Java学习笔记——新特性-注解

文章目录

  • Java学习笔记——新特性-注解
    • 1 三个基本的 Annotation
      • 1.1 @Override
      • 1.2 @Deprecated
      • 1.3 @SuppressWarnings
    • 2 自定义 Annotation
    • 3 元 Annotation
      • 3.1 @Retention
      • 3.2 @Target
      • 3.3 @Documented
      • 3.4 @Inherited
    • 4 利用反射获取注解信息

从 JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是 Annotation(注解)。

Annotation 其实就是代码里的特殊标记,这些标记可以在编译、类加载或运行时被读取,并执行相应的处理。通过使用 Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。

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

Annotation 能被用来为程序元素(类、方法、成员变量等)设置元数据。

1 三个基本的 Annotation

1.1 @Override

限定重写父类(或接口)的方法, 该注解只能用于方法。

interface Info{
	void show();
}

class Season{
	@Override
	public void show() {
		System.out.println("这是一个季节");
	}
}

虽然不加Override也可以识别重写的方法。但加了注解之后,有以下两个好处:

  • 便于调试

    如果该方法不是父类的方法(比如写错了方法名的某个字母)则编译器会报错,便于调试。

  • 一目了然

1.2 @Deprecated

用于表示某个程序元素(类, 方法等)已过时。

当某类或方法已经有更好的方式替代,但为了兼容性,又不能直接淘汰,就可以使用这个注解,这样新的程序开发时就可以看到这样的改变(用IDE开发时可以看到提示,比如过时的代码会被横线划掉),从而尽量避免使用过时的代码,而使用其替代方案。在一定的时间之后,当所有程序基本上都使用了新的方式时,旧的代码可能被淘汰。

@Deprecated(since="9")
public Integer(int value) {
	this.value = value;
}

1.3 @SuppressWarnings

抑制编译器警告。当有需要时,可以这样抑制一些编译器的警告,以满足程序员的“需求”,但使用时应知道自己在干什么。

@SuppressWarnings("unused")
public void printColl(@SuppressWarnings("rawtypes") Collection coll) {
    @SuppressWarnings("rawtypes")
    List list = new ArrayList();
    for(Object object : coll) {
        System.out.println(object);
    }
}

2 自定义 Annotation

  • 使用 @interface 关键字。
  • 成员变量在 Annotation 定义中以无参数方法的形式来声明。
  • 可使用 default 关键字指定成员变量的默认初始值。
  • 可用元注解对其进行注解(见下文)
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
public @interface MyAnnotation {
	String name() default "hello";
}

没有成员定义的 Annotation 称为标记;包含成员变量的 Annotation 称为元数据 Annotation。

3 元 Annotation

JDK 的元 Annotation 用于修饰其他 Annotation 定义。

JDK5.0提供了专门在注解上的注解类型。

几个基本注解的定义中就有元注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
    /**
     * Returns the version in which the annotated element became deprecated.
     * The version string is in the same format and namespace as the value of
     * the {@code @since} javadoc tag. The default value is the empty
     * string.
     *
     * @return the version string
     * @since 9
     */
    String since() default "";

    /**
     * Indicates whether the annotated element is subject to removal in a
     * future version. The default value is {@code false}.
     *
     * @return whether the element is subject to removal
     * @since 9
     */
    boolean forRemoval() default false;
}
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    /**
     * The set of warnings that are to be suppressed by the compiler in the
     * annotated element.  Duplicate names are permitted.  The second and
     * successive occurrences of a name are ignored.  The presence of
     * unrecognized warning names is not an error: Compilers must
     * ignore any warning names they do not recognize.  They are, however,
     * free to emit a warning if an annotation contains an unrecognized
     * warning name.
     *
     * 

The string {@code "unchecked"} is used to suppress * unchecked warnings. Compiler vendors should document the * additional warning names they support in conjunction with this * annotation type. They are encouraged to cooperate to ensure * that the same names work across multiple compilers. * @return the set of warnings to be suppressed */ String[] value(); }

3.1 @Retention

用于指定该 Annotation 可以保留多长时间, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用 @Rentention 时必须为该 value 成员变量指定值。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}
  • RetentionPolicy.SOURCE:编译器直接丢弃这种策略的注释。
  • RetentionPolicy.CLASS:编译器将把注释记录在 class 文件中。当运行 Java 程序时,JVM 不会保留注解。 这是默认值。
  • RetentionPolicy.RUNTIME:编译器将把注释记录在 class 文件中。当运行 Java 程序时,JVM 会保留注解。程序可以通过反射获取该注解。

3.2 @Target

用于指定被修饰的 Annotation 能用于修饰哪些程序元素。包含一个名为 value 的成员变量。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE,

    /**
     * Module declaration.
     *
     * @since 9
     */
    MODULE
}

3.3 @Documented

用于指定被被修饰的 Annotation 类将被 javadoc 工具提取成文档。

定义为 Documented 的注解必须设置 Retention 值为 RUNTIME。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

3.4 @Inherited

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

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

4 利用反射获取注解信息

JDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口,该接口代表程序中可以接受注解的程序元素。

程序可以调用 AnnotatedElement 对象的如下方法来访问 Annotation 信息。

Modifier and Type Method and Description
T getAnnotation(Class annotationClass) Returns this element’s annotation for the specified type if such an annotation is present, else null.
Annotation[] getAnnotations() Returns all annotations present on this element.
Annotation[] getDeclaredAnnotations() Returns all annotations that are directly present on this element.
boolean isAnnotationPresent(Class annotationClass) Returns true if an annotation for the specified type is present on this element, else false.

你可能感兴趣的:(java)