当前位置: 首页 > Thinking in Java > 正文

第 18 章 – Java 注解 – 总结

第 18 章 – 注解 – 总结

 

使用注解流程: 1 定义注解 2 定义注解处理器 3 使用注解

 

1.什么是注解

 

  方法前面使用@Override就是一个注解,表示被注解的方法必须要覆盖基类中的一个方法.

  @Deprecated注解表示API中的方法等是已经废弃的,程序中使用了废弃的方法会获得一个警告.

  @SuppresWarnings表示关闭编译器不必要的告警信息.

 

  注解是一种预先定义的规则 + 一些与之管理的注解处理器,可以在代码中按定义的规则使用注解,

  然后相关的注解处理器就会在适当的时机(编译时,或运行时)做出处理,已完成一些操作,或实现

  一些功能,尤其是一些重复的工作.

  比如,一共重复工作是根据一个类中的字段生成一个用于创建数据库表的sql.那么就可以定义一个

  注解应用在类中,然后定义注解处理器,传递这个类文件个注解处理器方法后,注解处理器根据类中

  的注解自动生成sql,不需要手工的根据类文件字段了手动创建sql.

 

  比如@Override这个符号就是一个注解定义,它要求必须要用在方法之前,该注解对应的处理器可以在

  编译时检查方法是否覆盖了基类的一个方法,如果没有则编译报错.

 

2. 定义注解

   定义注解主要是定义注解的属性,这些属性称为元注解,主要包括:

   (1) @Target 注解作用目标是什么,比如@Override注解的作用目标是类的方法.

       所有可用的注解作用目标有:

       ElementType.CONSTRUCTOR 构造器

       ElementType.FIELD 字段(包含enum类型的字段)

       ElementType.LOCAL_VARIABLE 局部变量

       ElementType.METHOD 方法

       ElementType.PACKAGE 包

       ElementType.PARAMETER 参数

       ElementType.TYPE 类,接口(包括注解类型本身)或enum声明

 

   (2) @Retention 表示要在什么级别保存该注解信息,所有的参数包括:

       RetentionPolicy.SOURCE 注解保存在源码中,会被编译器丢弃

       RetentionPolicy.CLASS 注解会保存在class中,但会被VM丢弃

       RetentionPolicy.RUNTIME VM在运行器也保留注解,因此可以通过反射机制读取注解

 

   (3) @Documented 表示将此注解包含在Javadoc中

 

   (4) @Inherited 表示允许子类集成父类中用到的注解

 

 注解元素,相当于注解的属性,可用的有:

 (1) 8种基本类型(boolean,char,byte,int,short,long,double,float)

 (2) String (3)Class (4) enum (5) Annotation

 (6) 以上类型的数组

 注解元素要么在定义是给个默认值,要么在使用时明确赋值.不能有不确定的值.

 

 定义注解类似于接口定义,使用@interface符号,

 注解元素定义也和接口方法定义差不多.

 

 定义注解的例子:

package annotations;

import java.lang.annotation.*;

@Target(ElementType.METHOD)     //表示注解的作用对象是方法
@Retention(RetentionPolicy.RUNTIME) //表示注解信息会在运行时保留
public @interface UseCase // 符号@interface用于定义注解
{
  
  public int id(); //整型注解元素

  public String description() default "no description"; //String型注解元素,带默认值
}

 

3. 定义注解处理器

 

   注解处理器中,通常使用反射获取注解信息,比如Class有 Annotation[] getAnnotations()方法,

   获取该Class上存在的所有注解,Method也有类似方法.

 

   需要注意的时,定义的注解 相当于集成了Annotation类,因此注解也是一种类型,注解实例可以同调用

   注解元素定义中的方法来获取注解元素值,比如UseCase.id()获取注解id元素的值.

 

   注解处理器不会自动触发,也是需要在代码中执行的.

   一般注解处理器是基于反射的,所以处理器中处理注解的方法需要传入一个Class类型的参数,

   这个Class就是在类定义代码中使用的注解的类.

   如下面UseCase的注解处理器trackUseCases中处理方法

   trackUseCases(useCases, PasswordUtils.class);就传递了一个参数PasswordUtils.class.

   而PasswordUtils类的源码中就使用了注解UseCase.

 

   PasswordUtils 类代码如下:

package annotations;

import java.util.*;

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);
  }
} 

 注解处理器代码如下:

package annotations;

import java.lang.reflect.*;
import java.util.*;

/**
 * 
 * 注解UseCase的处理器
 *
 */
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());
        //这里作为方法调用,获取了注解元素的值.
      }
    }
    
    for(int i: useCases)
    {
      System.out.println("warning: Missing use case-" + i);
    }
  }
  //List<Integer> useCases 这个参数表示注解处理器可能需要一些额外参数.
  //这里没有什么实际意义
  public static void main(String[] args)
  {
    List<Integer> useCases = new ArrayList<Integer>();
    Collections.addAll(useCases, 47,48,49,50);
    trackUseCases(useCases, PasswordUtils.class);
  }
}

 

赞 赏

   微信赞赏  支付宝赞赏


本文固定链接: https://www.jack-yin.com/coding/thinking-in-java/2099.html | 边城网事

该日志由 边城网事 于2015年03月16日发表在 Thinking in Java 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 第 18 章 – Java 注解 – 总结 | 边城网事

第 18 章 – Java 注解 – 总结 暂无评论

发表评论

快捷键:Ctrl+Enter