[疯狂Java讲义精粹] 第九章|Annotation(注释)

0. Java支持元数据(MetaData), 也就是Annotation(注释), 这种Annotation其实就是代码里的特殊标记, 这些标记可以在编译、类加载、运行时被读取, 并执行相应的处理. 

- 元数据 是"描述数据的数据(data about data)". 

- Annotation能被用来为程序元素(类、方法、成员变量等)设置元数据. 


1. Annotation(既是注释)也是一个接口, 程序可以通过反射来获取指定程序元素的Annotation对象, 然后通过Annotation对象来取得注释里的元数据. 


2. 访问和处理Annotation的工具统称APT(Annotation Processing Tool). 


3. 使用Annotation时要在其前面增加@符号, 并把该Annotation当成一个修饰符使用, 用于修饰它支持的程序元素. 四个基本Annotation:

  1. @Override: 强制一个方法必须覆盖父类的方法. (告诉编译器检查这个方法, 确保父类包含一个能被该方法重写的方法, 否则报错. @Override只能用于方法. )
  2. @Deprecated: 表示某个程序元素(类、方法等)已过时, 使用已过时的程序元素时, 便以其给出警告. 
  3. @SuppressWarnings: 使被修饰的程序元素(以及该程序元素中所有的子元素)取消显示指定的编译器警告. 使用时要在括号里使用name=value形式为该Annotation的成员变量设置值. 
    import java.util.*;
    
    @SuppressWarnings(value="unchecked")
    public class SuppressWarningsTest
    {
    	public static void main(String[] args)
    	{
    		List<String> myList = new ArrayList();
    	}
    }
  4. @SafeVarargs: Java7专门为抑制"堆污染(heap pollution)"警告提供的. 

4. jDK除了在java.lang下提供了4个基本的Annotation之外, 还在java.lang.annotation包下提供了4个Meta Annotation(元 Annotation), 这四个元Annotation都用于修饰其他的Annotation定义. 

  1. @Retention只能用于修饰一个Annotation定义, 用于指定被修饰的Annotation可以保留多长时间, @Retention包含一个RetentionPolicy类型的value成员变量, 所以使用@Retention时必须为该value成员变量指定值. 
    value成员变量的值只能是如下三种:
    - RetentionPolicy.CLASS: 编译器把Annotation记录在class文件中. 当运行Java程序时, JVM不再保留Annotation. 这是默认值. 
    - RetentionPolicy.RUNTIME: 编译器把Annotation记录在class文件中. 当运行Java程序时, JVM也会保留Annotation, 程序可以通过反射获取该Annotation信息. 
    - RetentionPolicy.SOURCE: Annotation只保留在源代码中, 编译器直接丢弃这种Annotation. 
    //定义Testable Annotation保留到运行时
    @Retention(value = RetentionPolicy.RUNTIME)
    public @interface Testable{}
    //等同于下面这样:
    @Retention(RetentionPolicy.RUNTIME)  //使用Annotation里名为value的成员变量时, 直接在括号里指定value值就行, 不必使用name=value形式. 
    public @interface Testable{}
  2. @Target也只能修饰一个Annotation定义, 它用于指定被修饰的Annotation能用于修饰哪些程序单元. @Target元Annotation也包含一个名为value的成员变量, 其值可能是如下几种:
    - ElementType.ANNOTATION_TYPE: 指定该策略的Annotation只能修饰Annotation.
    - ElementType.CONSTRUCTOR: 指定该策略的Annotation只能修饰构造器. 
    - ElementType.FIELD: 成员变量. 
    - ElementType.LOCAL_VARIABLE: 局部变量. 
    - ElementTpye.METHOD: 方法定义. 
    - ElementType.PACKAGE: 包定义. 
    - ElementType.PARAMETER: 参数. 
    - ElementType.TYPE: 指定该策略的Annotation可以修饰类、接口(包括注释类型)或枚举定义. 
  3. @Documented用于指定被该元Annotation修饰的Annotation类将被javadoc工具提取成文档, 如果定义Annotation类时使用了@Documented修饰, 则所有使用该Annotation修饰的程序元素的API文档中将或包含该Annotation说明. 
  4. @Inherited 元Annotation指定被他修饰的Annotation将具有继承性(如果某个类使用了@A  Annotation(定义该Annotation时使用了@Inherited修饰)修饰, 则其子类将自动被@A 修饰.). 

5. 定义新的Annotation类型 使用@interface关键字, 定义一个新的Annotation类型与定义一个接口很像, 如下代码可以定义一个简单的Annotation类型:
public @interface Test
{}

 或者带成员变量的Annotation(成员变量在Annotation中以无形参的方法的形式, 方法名和其返回值定义了该成员变量的名字和类型.):

public @interface MyTag
{
	String name();
	int age() default 32;  // 用default关键字为Annotation的成员变量指定初始值. 
}
 

6. 根据Annotation是否包含成员变量, 将其分两类.

  1. 标记Annotation: 没有成员变量的Annotation. 这种Annotation利用自身存在与否来提供信息.
  2. 元数据Annotation: 包含成员变量的Annotation. 因为它们能接受更多的元数据, 所以也被称为元数据Annotation. 

7. 使用Annotation的语法类似于修饰符, 可用于类、接口、方法、变量等, 通常放在修饰符之前单独一行. 带有成员变量的Annotation使用时必须制定成员变量的值(或定义时指定初始值(默认值).). 


8. 提取Annotation信息. .  ..  .这章写的真乱.

  1. 当一个Annotation类型被定义为运行时Annotation后, 该Annotation才会在运行时可见, JVM才会在装在*.class文件时读取保存在class文件中的Annotation. 
  2. java.lang.reflect包下的AnnotatedElement接口代表程序中可以接受注释的程序元素. 其主要实现类:
    - Class: 类定义. 
    - Constructor: 构造器定义. 
    - Field: 类成员定义. 
    - Method: 类的方法定义. 
    - Package: 类的包定义. 
  3. 程序通过反射获取某个类的AnnotatedElement对象(如Class、Method等)之后, 就可以通过调用该对象的如下三个方法来访问Annotation信息. 
    - getAnnotation(Class<T> annotationClass): 返回该程序元素上存在的指定类型的注释, 若不存在, 返回null. 
    - Annotation[] getAnnotations(): 返回该程序元素上存在的所有注释. 
    - boolean isAnnotationPresent(Class<? extends Annotation> annotationClass): 判断该程序元素上是否存在指定类型的注释, 存在返true, 木有返false. 

9. APT(Annotation Processing Tool, 注释处理工具) 可以找出源码中的Annotation, 并对其进行额外的处理. Annotation处理器在处理Annotation时会生成额外的源文件和其他的文件(文件具体内容由Annotation处理器的编写者决定), APT还会用编译生成的源代码文件和原来的源文件一起生成class文件. (APT可以在编译是生成一些附属文件, 如源文件、类文件、程序发布描述文件等.) 

10. javac.exe工具可以使用-processor选项指定一个Annotation处理器, 指定的处理器将在编译过程中处理源文件中的Annotation. 

11. 每个Annotation处理器都必须实现javax.annotation.processing包下的Processor接口. 不过, 通常采用集成AbstractProcessor的方式避免实现Processor过多的方法. (核心类位于java包及其子包下, 扩展类位于javax包及其子包下.) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值