Subject: |
[Java Annotation] |
Description: |
1.定义自己的注释类型 定义新的注释类型与创建接口有很多类似之处,只不过 interface 关键字之前要有一个 @ 符号。 package com.oreilly.tiger.ch06; /** * Marker annotation to indicate that a method or class * is still in progress. */ public @interface InProgress { } 2.使用定制的注释类型 @com.oreilly.tiger.ch06.InProgress public void calculateInterest(float amount, float rate) { // Need to finish this method later } 当然,一般的 Java 规则仍然适用,您可以导入该注释类型,直接使用 @InProgress 引用它。 3.定义和使用注释的成员变量 定义数据成员后不需要分别定义访问和修改的方法。相反,只需要定义一个方法,以成员的名称命名它。数据类型应该是该方法返回值的类型。 package com.oreilly.tiger.ch06; /** * Annotation type to indicate a task still needs to be * completed. */ public @interface TODO { String value(); } 如果在annotations中只有唯一一个成员,则该成员应命名为value。 4.给注释的成员赋于默认值 package com.oreilly.tiger.ch06; public @interface GroupTODO { public enum Severity { CRITICAL, IMPORTANT, TRIVIAL, DOCUMENTATION }; Severity severity() default Severity.IMPORTANT; String item(); String assignedTo(); String dateAssigned(); } 注上述程序清单中:另一个新特性是注释类型定义了自己的枚举。 使用默认值 @com.oreilly.tiger.ch06.InProgress @GroupTODO( //severity=GroupTODO.Severity.DOCUMENTATION, item="Need to explain how this rather unusual method works", assignedTo="Jon Stevens", dateAssigned="07/30/2004" ) public void reallyConfusingMethod(int codePoint) { // Really weird code implementation } 5.对注释的注释 在编写自己的注释类型时,注释类型的目的并不总是显而易见的。除了基本的文档外,可能还要针对某个特定的成员类型或者一组成员类型编写类型。这就要求您为注释类型提供某种元数据,以便编译器保证按照预期的目的使用注释。 1)指定目标 允许何种程序元素具有定义的注释类型。毫不奇怪,这种元注释被称为 Target 。在了解如何使用 Target 之前,您还需要认识另一个类,该类被称为 ElementType ,它实际上是一个枚举。这个枚举定义了注释类型可应用的不同程序元素。 package java.lang.annotation; public enum ElementType { TYPE, // Class, interface, or enum (but not annotation) FIELD, // Field (including enumerated values) METHOD, // Method (does not include constructors) PARAMETER, // Method parameter CONSTRUCTOR, // Constructor LOCAL_VARIABLE, // Local variable or catch clause ANNOTATION_TYPE, // Annotation Types (meta-annotations) PACKAGE // Java package } 使用 Target 元注释时,至少要提供这些枚举值中的一个并指出注释的注释可以应用的程序元素。 2)设置保持性 Retention ,这个元注释和 Java 编译器处理注释的注释类型的方式有关。编译器有几种不同选择: · 将注释保留在编译后的类文件中,并在第一次加载类时读取它。 · 将注释保留在编译后的类文件中,但是在运行时忽略它。 · 按照规定使用注释,但是并不将它保留到编译后的类文件中。 这三种选项用 java.lang.annotation.RetentionPolicy 枚举表示, package java.lang.annotation; public enum RetentionPolicy { SOURCE, // Annotation is discarded by the compiler CLASS, // Annotation is stored in the class file, but ignored by the VM RUNTIME // Annotation is stored in the class file and read by the VM } 使用RetentionPolicy 清单 13 @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { // annotation type body } 这里可以使用简写形式,因为 Retention 只有一个成员变量。如果要将保持性设为 RetentionPolicy.CLASS ,那么什么也不需要做,因为这就是默认行为。Documented 的一个实用技巧是保持性策略。注意,清单 13 中规定注释的保持性(retention)是 RUNTIME ,这是使用 Documented 注释类型所 必需的。Javadoc 使用虚拟机从其类文件(而非源文件)中加载信息。确保 VM 从这些类文件中获得生成 Javadoc 所需信息的惟一方法是将保持性规定为 RetentionPolicy.RUNTIME 。这样,注释就会保留在编译后的类文件中 并且由虚拟机加载,然后 Javadoc 可以从中抽取出来添加到类的 HTML 文档中。 3) 添加公共文档 Documented 表示注释应该出现在类的 Javadoc 中。在默认情况下,注释 不包括在 Javadoc 中. 4)设置继承 首先考虑这样一种情况:假设您通过定制的 InProgress 注释标记一个类正在开发之中,这完全没有问题,对吧?这些信息还会出现在 Javadoc 中,只要您正确地应用了 Documented 元注释。现在,假设您要编写一个新类,扩展那个还在开发之中的类,也不难,是不是?但是要记住,那个超类还在开发之中。如果您使用子类,或者查看它的文档,根本没有线索表明还有什么地方没有完成。您本来希望看到 InProgress 注释被带到子类中 —— 因为这是 继承 的 —— 但情况并非如此。您必须使用 Inherited 元注释说明所期望的行为, package com.oreilly.tiger.ch06; import java.lang.annotation.Documented; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Marker annotation to indicate that a method or class * is still in progress. */ @Documented @Inherited @Retention(RetentionPolicy.RUNTIME) public @interface InProgress { } 添加 @Inherited 后,您将看到 InProgress 出现在注释类的子类中。当然,您并不希望所有的注释类型都具有这种行为(因此默认是 不 继承的)。
6.注释VS配置文件 对于总要与特定 Java 组件(类、方法或字段)连接的配置信息,用注释表示是一个好的选择。因为注释方面的限制,所以当每个组件只有一个配置时,注释也是最适合的。如果需要处理多重配置,特别是配置取决于包含注释的 Java 类之外的东西时,注释带来的问题可能要比它们解决的问题还要多。最后,如果不重新编译 Java 源代码,就不能修改注释,所以要求在运行时配置的内容不能使用注释。 用注释将配置嵌入代码中会使代理和配置都难以被人们所理解。我将数据绑定函数看作是将要应用到程序程序的方面(从 AOP 的角度),这甚至超出了这个混淆问题的范围。AOP 的立场来看,最好是把方面信息(在该例是绑定定义)放在代码之外。 |
Refer url: |
http://www.ibm.com/developerworks/cn/java/j-annotate2.html |