注解的定义和使用

2016-08-25 14:37:10   最后更新: 2016-08-25 14:37:10   访问数量:452




java 注解也被称为“元数据”,他是 jdk1.5 引入的 java 特性

java 注解可以用于创建文档、跟踪代码依赖性、甚至基本的编译时、运行时检查,它可以灵活的实现模板代码的生成,或者为程序的相关部分引入额外信息

注解以 @ 符号 + 注解名为标识在代码中存在,编译器在编译期自动加载它们的代码到相应的位置使用

 

java5 的 java.lang 包中内置了三种注解:

  1. @Override -- 标识当前的方法将覆盖父类中的方法,虽然在实现覆盖时并不要求必须加上该注解,但该注解可以强制检查覆盖的完成,这样编译器可以在你拼写错误时发出错误提示
  2. @Deprecated -- 标识已经废弃的元素,一旦程序员使用了这些元素,编译器会发出警告
  3. @SuppressWarnings -- 关闭不当的编译器警告

 

如果要创建一个注解,就需要使用元注解了,所谓的元注解,就是注解其他注解的注解,也就是在定义其他注解时需要使用的注解,他们标识了自定义注解的行为

java5 定义了下面五个元注解中的前四个,java8 则定义了最后一个元注解:

  1. @Target -- 注解应用的地方
  2. @Retention -- 注解可用的级别
  3. @Documented -- 用于生成文档
  4. @Inherited -- 允许子类继承父类中的注解
  5. @Repeatable -- 允许重复注解

 

@Target

@Target 说明了注解修饰的对象范围,它的取值是 java.lang.annotation.ElementType 枚举对象,对象中声明了下面的枚举实例:

  1. CONSTRUCTOR -- 构造器的声明
  2. FIELD -- 域声明(包括 enum 实例)
  3. LOCAL_VARIABLE -- 局部变量声明
  4. PACKAGE -- 包声明
  5. PARAMETER -- 参数声明
  6. TYPE -- 用于描述类、接口(包括注解类型)或 enum 声明
  7. ANNOTATION_TYPE -- 注释声明
  8. METHOD -- 方法声明
  9. TYPE_PARAMETER -- 类型变量声明语句中
  10. TYPE_USE -- 使用类型的任何语句中(如声明、泛型、强制转换语句中的类型)

 

最后的两个是 java8 引入的新特性,很大程度的扩展了注解的使用范围,使用前面 8 种 ElementType,可以让注解在指定的声明位置使用,而使用最后的两种 ElementType,注解可以被用在几乎所有场合

 

支持注解的元素的类型包括:

  1. 所有基本类型(但不能注解基本类型的打包类型)
  2. String
  3. Class
  4. enum
  5. Annotation
  6. 以上类型的数组类型

如果注解其他类型的元素,编译器在编译时将报错

 

@Retention

表示需要什么级别保存该注解信息,他的取值是 java.lang.annotation.RetentionPolicy 枚举对象,对象中声明了下列枚举实例:

  1. SOURCE -- 注解将被编译器丢弃
  2. CLASS -- 注解在 class 文件中可用,但会被 VM 丢弃
  3. RUNTIME -- jvm 在运行期可以使用该注解,同时也可以通过反射机制读取注解信息

 

使用注解的过程中,最重要的一个部分就是创建与使用注解处理器

 

下面的例子展示了使用反射的方法处理注解的注解处理器

 

annotation.Test

package com.techlog.test.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by techlog on 16/5/24. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Test { public int id(); public String desc() default "none"; }

 

 

ForTest

package com.techlog.test.service; import com.techlog.annotation; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; /** * just for test * Created by techlog on 16/5/20. */ public class ForTest { public static void fortest(List<Integer> useCases, Class<?> cl) { for (Method method : cl.getDeclaredMethods()) { Test test = method.getAnnotation(Test.class); if (test != null) { System.out.println("Found Test Annotation: " + test.id() + ", description: " + test.desc()); } } } public static void main(String[] argv) { List<Integer> useCases = Arrays.asList(47, 48, 49, 50); fortest(useCases, TestAnnotation.class); } } class TestAnnotation { @Test(id = 47, desc = "equals passwd") public boolean validatePassword(String passworld) { return passworld.equals("passwd"); } @Test(id = 48, desc = "saySome") public String saySome(String content) { return content + " !"; } }

 

 

输出了:

Found Test Annotation: 47, description: equals passwd

Found Test Annotation: 48, description: saySome

 

说明

上面的代码中,在 @Test 注解中加入了我们需要的属性,并运用反射机制获取到了注解的属性值

有时,我们使用一些没有元素的注解,称为“标记注解”,仅用于标记和跟踪一个项目中的使用

 

在 Test 注解的 desc 元素的声明中,我们使用 default 关键字指定了他的默认值,需要注意的是,注解元素默认值的定义不能以 null 作为默认值

 






读书笔记      技术帖      龙潭书斋      java      注解      annotation      thinking in java     


京ICP备15018585号