《java编程思想》第二十章 注解

JavaSE5内置了三种标准注解,定义在java.lang中的注解:

@Override,表示当前的方法定义将覆盖超类中的方法。如果没有重写,编译器会发出错误提示。

@Deprecated,如果程序员使用了该注解注解过的元素,那么编译器会发出警告信息。

@SuppressWarnings,关闭不当的编译器警告信息。

 

元注解是负责注解其他的注解,有四种元注解:

@Target 表示该注解可以用于什么地方。可能的ElementType(枚举)参数包括:

CONSTRUCTOR:构造方法声明

FIELD:域声明(包括enum实例)

LOCAL_VARIABLE:局部变量声明

METHOD:方法声明

PACKAGE:包声明

PARAMETER:参数声明

TYPE:类,接口(包括注解类型)或enum声明

@Retention 表示需要在什么级别保存注解信息。可用的RetentionPolicy(枚举)参数包括:

SOURCE:注解将被编译地器丢弃。

CLASS:注解在class文件中可用,但会被VM丢弃。

RUNTIME:VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息。

@Documented 将此注解包含在JavaDoc中。

@Inherited 允许子类继承父类中的注解。

 

Class、Method、Field、Constructor类都实现了AnnotatedElement接口,他们的getAnnotation方法都返回指定类型的注解对象,如果没有该类型的注解,则返回null值,以下是这些方法的原型:

class. getAnnotation(Class<T> annotationClass)

method. getAnnotation(Class<T> annotationClass)

field. getAnnotation(Class<T> annotationClass)

constructor. getAnnotation(Class<T> annotationClass)

 

注解的定义看起来很像接口的定义,事实上,与其他任何Java接口一样,注解也会编译成class文件。

 

 

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

/*

* 这是一个简单的注解,我们可以用它来跟踪一个项目中的用例。如果一个方法

* 或一组方法实现了某个用例的需求,那么程序员可以为此方法加上该注解。

*/

 

//注解的定义

@Target(ElementType.METHOD)//该注解用于方法

@Retention(RetentionPolicy.RUNTIME)//注解信息保留到运行期

public @interface UseCase {

  public int id();//int型的元素

  public String description() default "no description";//String型的元素

}

 

//注解的使用

class PasswordUtils {

  @UseCase(id = 47, 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();

  }

  @UseCase(id = 49, description = "新密码不能使用以前使用过的密码")

  public boolean checkForNewPassword(

    List<String> prevPasswords, String password) {

    return !prevPasswords.contains(password);

  }

}

 

//注解处理器

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("找到用例:" + uc.id() +

          " " + uc.description());

        useCases.remove(new Integer(uc.id()));

      }

    }

    for(int i : useCases) {

      System.out.println("警告: 所缺用例-" + i);

    }

  }

  public static void main(String[] args) {

    List<Integer> useCases = new ArrayList<Integer>();

    Collections.addAll(useCases, 47, 48, 49, 50);

    trackUseCases(useCases, PasswordUtils.class);

  }

}

/*

找到用例:47 密码必须至少包含一个数字

找到用例:48 no description

找到用例:49 新密码不能使用以前使用过的密码

警告: 所缺用例-50

*/

 

 

注解里的组成元素类型:

1、  所有基本类型

2、  String

3、  Class

4、  enum

5、  Annotation

6、  以上类型的数组

如果你使用了其他类型,那编译器就会报错。

 

注解组成元素的默认值限制:首先,元素不能有不确定的值,也就是说,元素必须要么具有默认值,要么在使用注解时提供元素的值,不允许即没给定默认值,在使用进也没指定值的情况出现。其次,对于非基本类型的元素,无论是在声明还是在使用时,都不能以null作为其值。

 

注解不支持继承。

猜你喜欢

转载自blog.csdn.net/fromatozhappy/article/details/52751894