Skip to content

Latest commit

 

History

History
160 lines (120 loc) · 5.87 KB

21 注解.md

File metadata and controls

160 lines (120 loc) · 5.87 KB
title toc date
21 注解
false
2017-10-30

Annotations (注解, also known as metadata) provide a formalized way to add information to your code so that you can easily use that data at some later point.

The syntax of annotations is reasonably simple and consists mainly of the addition of the @symbol to the language. Java SE5 contains three general purpose built-in annotations, defined in java.lang:

  • @Override, to indicate that a method definition is intended to override a method in the base class. This generates a compiler error if you accidentally misspell the method name or give an improper signature.
  • @Deprecated, to produce a compiler warning if this element is used.
  • @SuppressWarnings, to turn off inappropriate compiler warnings.

1 Basic syntax

Defining annotations

Annotation definitions look a lot like interface definitions. In fact, they compile to class files like any other Java interface:

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface Test {} //注意在interface之前有@符号

An annotation definition also requires the meta-annotations @Target and @Retention. @Target defines where you can apply this annotation (a method or a field, for example). @Retention defines whether the annotations are available in the source code, in the class files, or at run time.

Annotations will usually contain elements to specify values in your annotations. An annotation without any elements, such as @Test above, is called a marker annotation.

Here is a simple annotation that tracks use cases in a project. id and description are elements, which resemble method declarations.

@Target(ElementType.METHOD) // 注解的目标
@Retention(RetentionPolicy.RUNTIME)  // 注解信息保留到什么时候
public @interface UseCase {
    public int id();
    public String description() default "no description"; 
}

Here is a class with three methods annotated as use cases:

public class PasswordUtils {
  @UseCase(id = 47, description =
  "Passwords must contain at least one numeric")
  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();
  }
  @UseCase(id = 49, description =
  "New passwords can't equal previously used ones")
  public boolean checkForNewPassword(
    List<String> prevPasswords, String password) {
    return !prevPasswords.contains(password);
  }
}

Note that values of the annotation elements are expressed as name-value pairs in parentheses.

!!! note "@Override注解"

```java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
```

Meta-annotations

There are currently only three standard annotations (described earlier) and four meta-annotations(元注解) defined in the Java language. The meta-annotations are for annotating annotations:

  • @Target: Where this annotation can be applied. The possible ElementType arguments are:
    • CONSTRUCTOR: Constructor declaration
    • FIELD: Field declaration (includes enum constants)
    • LOCAL_VARIABLE: Local variable declaration
    • METHOD: Method declaration
    • PACKAGE: Package declaration
    • PARAMETER: Parameter declaration
    • TYPE: Class, interface (including annotation type), or enum declaration
  • @Retention: How long the annotation information is kept. The possible RetentionPolicy arguments are:
    • SOURCE: Annotations are discarded by the compiler.
    • CLASS: Annotations are available in the class file by the compiler but can be discarded by the VM.
    • RUNTIME: Annotations are retained by the VM at run time, so they may be read reflectively.
  • @Documented: Include this annotation in the Javadocs.
  • @Inherited: Allow subclasses to inherit parent annotations.

2 Writing annotation processors

查看注解信息

当@Retention�为RetentionPolicy.RUNTIME�时,利用反射机制在运行时可以查看注解信息。

// 获取所有的注解
public Annotation[] getAnnotations()
// 获取所有本元素上直接声明的注解,忽略继承来的
public Annotation[] getDeclaredAnnoations()
// 获取制定类型的注解,没有返回null
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
// 判断是否有指定类型的注解
public boolean isAnnotationPresent(
        Class<? extends Annotation> annotationClass)

其中Annotation是一个接口,表示注解:

public interface Annotation {
    boolean equals(Object obj);
    int hashCode();
    String toString();
    // Returns the annotation type of this annotation.
    Class<? extends Annotation> annotationType();
}

Here is a very simple annotation processor(注解处理器) that reads the annotated PasswordUtils class and uses reflection to look for @UseCase tags. Given a list of id values, it lists the use cases it finds and reports any that are missing:

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);
    }
  }
  public static void main(String[] args) {
    List<Integer> useCases = new ArrayList<Integer>();
    Collections.addAll(useCases, 47, 48, 49, 50);
    trackUseCases(useCases, PasswordUtils.class);
  }
}