转自:http://hi.baidu.com/sword0228/item/5344d9bed46d0f44bb0e126e
Java Annotation入门(二)(中英文结合)
It is permissible to omit the parentheses in marker annotations, as shown below:
@Preliminary public class TimeTravel { ... }
In annotations with a single element, the element should be named value
, as shown below:
如果annotation只有一个元素,那这个元素应该被命名为value,如下:
/*** Associates a copyright notice with the annotated API element.*/public @interface Copyright {String value();}
It is permissible to omit the element name and equals sign (=
) in a single-element annotation whose element name isvalue
, as shown below:
单一元素命名为value的Annotaion允许省略元素名和等号(=),如下:
@Copyright("2002 Yoyodyne Propulsion Systems")public class OscillationOverthruster { ... }
To tie it all together, we'll build a simple annotation-based test framework. First we need a marker annotation type to indicate that a method is a test method, and should be run by the testing tool:
import java.lang.annotation.*;/*** Indicates that the annotated method is a test method.* This annotation should be used only on parameterless static methods.*/@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface Test { }
Note that the annotation type declaration is itself annotated. Such annotations are calledmeta-annotations. The first (@Retention(RetentionPolicy.RUNTIME)
) indicates that annotations with this type are to be retained by the VM so they can be read reflectively at run-time. The second (@Target(ElementType.METHOD)
) indicates that this annotation type can be used to annotate only method declarations.
Here is a sample program, some of whose methods are annotated with the above interface:
public class Foo {@Test public static void m1() { }public static void m2() { }@Testpublic static void m3() {throw new RuntimeException("Boom");}public static void m4() { }@Test public static void m5() { }public static void m6() { }@Test public static void m7() {throw new RuntimeException("Crash");}public static void m8() { }}
Here is the testing tool:
import java.lang.reflect.*;public class RunTests {public static void main(String[] args) throws Exception {int passed = 0, failed = 0;for (Method m : Class.forName(args[0]).getMethods()) {if (m.isAnnotationPresent(Test.class)) {try {m.invoke(null);passed++;} catch (Throwable ex) {System.out.printf("Test %s failed: %s %n", m, ex.getCause());failed++;}}}System.out.printf("Passed: %d, Failed %d%n", passed, failed);}}
The tool takes a class name as a command line argument and iterates over all the methods of the named class attempting to invoke each method that is annotated with theTest
annotation type (defined above). The reflective query to find out if a method has aTest
annotation is highlighted in green. If a test method invocation throws an exception, the test is deemed to have failed, and a failure report is printed. Finally, a summary is printed showing the number of tests that passed and failed. Here is how it looks when you run the testing tool on the Foo
program (above):
$ java RunTests Foo Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash Passed: 2, Failed 2
While this testing tool is clearly a toy, it demonstrates the power of annotations and could easily be extended to overcome its limitations.