《Java 编程思想》--第二十章:注解

  1. 注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据
  2. 注解可以提供用来完整地描述程序所需的信息,而这些信息是无法用Java来表达的。因此,注解使得我们能够以将由编译器来测试和验证的格式,存储有关程序的额外信息
  3. 几个注解:
    1. @Override:表示当前的方法定义将覆盖超类中的方法
    2. @Deprecated:如果程序员使用了注解为它的元素,那么编译器会发出警告信息
    3. @SuppressWarnings:关闭不当的编译器警告信息
  4. 注解是正真的语言机的概念,一旦构造出来,就像有编译期的类型检查保护。注解是在实际的源代码级别保存所有的信息,而不是某种注释性文字,使得代码更整洁,且便于维护
  5. 定义注解实例:
    1. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      package annotationTest;
       
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
       
       
      @Target (ElementType.METHOD)
      @Retention (RetentionPolicy.RUNTIME)
      public @interface Test{}

    2. 在定义注解时,会需要一些元注解,如@Target和@Retention:
      1. @Targer:用来定义你的注解将应用于什么地方,一个方法或者一个域
      2. @Retention:用来定义该注解是哪一级别可用,在源代码中(SOURCE)、类文件中(CLASS)或者运行时(RUNTIME)
    3. 在注解中一般都会包含一些元素以表示某些值,当分析处理注解时,程序或工具可以利用这些值。注解的元素看起来就像接口的方法,唯一区别是你可以为其指定默认值。没有元素的注解称为标记注解,例如@Test
      1. 包含值的注解UserCase:
        1. 1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          package annotationTest;
           
          import java.lang.annotation.ElementType;
          import java.lang.annotation.Retention;
          import java.lang.annotation.RetentionPolicy;
          import java.lang.annotation.Target;
           
          @Target (ElementType.METHOD)
          @Retention (RetentionPolicy.RUNTIME)
          public @interface UserCase {
               public int id();
           
               public String description() default "no description" ;
          }

        2. 如上可以看到description元素有一个default值,如果在注解某个方法时没有各处description的值,则该注解的处理器就会使用此元素的默认值”no description“
      2. 包含值的注解UserCase的实例:
        1. 1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          package annotationTest;
           
          import java.util.List;
           
          public class PasswordUtils {
               @UserCase (id = 47 , description = "Passwords must contatin at least one numeric" )
               public boolean validatePassword(String password) {
                   return (password.matches( "\\w*\\d\\w*" ));
               }
           
               @UserCase (id = 48 )
               public String encryptPassword(String password) {
                   return new StringBuilder(password).reverse().toString();
               }
           
               @UserCase (id = 49 , description = "New passwords can't equal previously used ones" )
               public boolean checkForNewPassword(List prevPasswords,
                       String password) {
                   return !prevPasswords.contains(password);
               }
           
          }

        2. 注解的元素在使用时表现为名-值对的形式
  6. 元注解:
    1. Java目前只内置了三种标准注解,以及四种元注解。元注解专职负责注解其他的注解:
      1. @Target:表示该注解可以用于什么地方,其ElementType参数包括:
        1. CONSTRUCTOR:构造器的声明
        2. FIELD:域声明(包括enum实例)
        3. LOCAL_VARIABLE:局部变量声明
        4. METHOD:方法声明
        5. PACKAGE:包声明
        6. PARAMETER:参数声明
        7. TYPE:类、接口(包括注解类型)或enum声明
      2. @Retention:表示需要在什么级别保存该注解信息,可选的RetentionPolicy参数有:
        1. SOURCE:注解将被编译器丢弃
        2. CLASS:注解在class文件中可用,但会被VM丢弃
        3. RUNTIME:VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息
      3. @Documented:将此注解包含在Javadoc中
      4. @Inherited:允许子类继承父类中的注解
  7. 编写注解处理器:
    1. 如果没有用来读取注解的工具,那注解不会比注释更有用。使用注解的过程中,很重要的一个部分就是创建与使用注解处理器
    2. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      package annotationTest;
       
      import java.lang.reflect.Method;
      import java.util.ArrayList;
      import java.util.Collections;
      import java.util.List;
       
      public class UserCaseTracker {
           public static void trackUserCases(List useCases, Class cl) {
               for (Method m : cl.getDeclaredMethods()) {
                   UserCase uc = m.getAnnotation(UserCase. 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 useCases = new ArrayList();
               Collections.addAll(useCases, 47 , 48 , 49 , 50 );
               trackUserCases(useCases, PasswordUtils. class );
           }
       
      }

    3. 上面这段程序使用到了两个反射方法:getDeclaredMethods()和getAnnotation(),他们都属于AnnotatedElement接口。getAnnotation()方法返回指定类型的注解对象,也就是UseCase
  8. 注解元素可用的类型:
    1. 所有基本类型
    2. String
    3. Class
    4. enum
    5. Annotation
    6. 以上类型的数组

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