《Java编程思想》笔记20-注解

  1. 定义注解
  2. 元注解
  3. 注解元素
  4. 编写注解处理器
  5. javac 处理注解

Java SE5 内置了三种,定义在 java.lang 中的注解:

  • @Override,表示当前的方法定义将覆盖超类中的方法。如果你不小心拼写错误,或者方法签名对不上被覆盖的方法,编译器就会发出错误提示。
  • @Deprecated,如果程序员使用了注解为它的元素,那么编译器会发出警告信息(过时)
  • @SuppressWarnings,关闭不当的编译器警告信息。在 Java SE5 之前的版本中,也可以使用该注解,不过会被忽略不起作用。

每当你创建描述符性质的类或接口时,一旦其中包括了重复性的工作,那就可以考虑使用注解来简化与自动化该过程。

定义注解

注解的定义很像接口的定义,也会编译成 class 文件。注解不支持继承

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
    public int id();
    public String description() default "no description"; // 默认值
}
public class PasswordUtils {
    @UseCase(id=47, description="description")
    public boolean validatePassword(String password) {
        return (password.matches("\\w*\\d\\w*"));
    }
    @UseCase(id = 48)
    public String encryptPassword(String password) {
        return new StringBuilder(password).reverse().toString();
    }
}

定义默认值时,不能以 null 作为其值。一般可以自己定义一些特殊的值,如空字符或负数,表示某个元素不存在。

元注解

注解 说明
@Target 定义注解应用的地方。ElementType 参数包括:
CONSTRUCTOR:构造器的声明;
FIELD:域声明(包括 enum 实例);
LOCAL_VARIABLE:局部变量声明;
METHOD:方法声明;
PACKAGE:包声明;
PARAMETER:参数声明;
TYPE:类、接口或enum声明
@Retention 定义注解应用的级别。RetentionPolicy 参数包括:
SOURCE:注解将被编译器丢弃;
CLASS:注解在 class 文件中可用,但会被 VM 丢弃;
RUNTIME:VM 将在运行期也保留注解,因此可通过反射机制读取注解信息
@Documented 将此注解包含在 JavaDoc 中
@Inherited 允许子类继承父类中的注解

ElementType 参数,可以只指定某一个值,也可以以逗号分隔的形式指定多个值,如果想将注解应用于所有的 ElementType,那么可以省去 @Target 元注解,不过不常用。

注解元素

注解元素可用的类型包括:

  • 所有基本类型
  • String
  • Class
  • enum
  • Annotation
  • 所有前面这些类型的数组

不允许使用任何包装类型(有自动装箱存在,所以算不上什么限制),注解可以嵌套。

如果元素值是一个数组,要将它的值用大括号括起来 @Test(array={"a","b"}),如果只有一个值,也可以省去括号。

注解中定义了名为 value 的元素,且在应用该注解时,若该元素是唯一需赋值元素,则无需使用名-值对语法,只需在括号内给出 value 值即可。

编写注解处理器

public class UseCaseTracker {
  public static void trackUseCases(List<Integer> useCases, Class<?> cl) {
    for(Method m : cl.getDeclaredMethods()) {
      UseCase uc = m.getAnnotation(UseCase.class);
      if(uc != null) {
        System.out.println("Found Use Case:" + uc.id() + " " + uc.description());
        useCases.remove(new Integer(uc.id()));
      }
    }
    for(int i : useCases) {
      System.out.println("Warning: Missing use case-" + i);
    }
  }
}

反射方法 getDeclaredMethods()getAnnotation() 均属于 AnnotationElement 接口,Class、Method、Field 均实现了该接口。

getAnnotation() 方法返回指定类型的注解对象。如果没有则返回 null。使用反射获取到注解对象之后,类似使用调用方法的方式获取注解的值,如uc.id()等。

getDeclaredAnnotations() 返回直接存在于此元素上的所有注释。也属于 AnnotationElement 接口。

javac 处理注解

Java SE 6 引入了一个新的功能,叫做 可插入注解处理(Pluggable Annotation Processing) 框架,它提供了标准化的支持来编写自定义的注解处理器。之所以称为“可插入”,是因为注解处理器可以动态插入到 javac 中,并可以对出现在 Java 源文件中的一组注解进行操作。此框架具有两个部分:一个用于声明注解处理器并与其交互的 API 包 javax.annotation.processing 和一个用于对 Java 编程语言进行建模的 API 包 javax.lang.model

http://howiefh.github.io/2014/11/06/thinking-in-java-note-7/#javac处理注解



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com

文章标题:《Java编程思想》笔记20-注解

文章字数:1k

本文作者:Bin

发布时间:2018-06-24, 16:48:03

最后更新:2019-08-06, 00:46:42

原始链接:http://coolview.github.io/2018/06/24/Java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/%E3%80%8AJava%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3%E3%80%8B%E7%AC%94%E8%AE%B020-%E6%B3%A8%E8%A7%A3/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录