命名模式的缺点有以下三点:(在第 4 版之前,JUnit 测试框架要求其用户通过以 test[Beck04] 开始名称来指定测试方法)
1.拼写错误导致失败,但不会提示。
2.无法确保它们仅用于适当的程序元素。
3.它们没有提供将参数值与程序元素相关联的好的方法。
下面以Junit4为例来说明注解的优势
/** * Indicates that the annotated method is a test method. * Use only on parameterless static methods. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Test { }
// Program to process marker annotations import java.lang.reflect.*;
public class RunTests { public static void main(String[] args) throws Exception { int tests = 0; int passed = 0; Class<?> testClass = Class.forName(args[0]); for (Method m : testClass.getDeclaredMethods()) { if (m.isAnnotationPresent(Test.class)) { tests++; try { m.invoke(null); passed++; } catch (InvocationTargetException wrappedExc) { Throwable exc = wrappedExc.getCause(); System.out.println(m + " failed: " + exc); } catch (Exception exc) { System.out.println("Invalid @Test: " + m); } } } System.out.printf("Passed: %d, Failed: %d%n",passed, tests - passed); }
}
从 Java 8 开始,还有另一种方法来执行多值注解。 可以使用 @Repeatable 元注解来标示注解的声明,而不用
使用数组参数声明注解类型,以指示注解可以重复应用于单个元素。
// Repeatable annotation type @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Repeatable(ExceptionTestContainer.class) public @interface ExceptionTest { Class<? extends Exception> value(); }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExceptionTestContainer { ExceptionTest[] value(); }
// Code containing a repeated annotation
@ExceptionTest(IndexOutOfBoundsException.class)
@ExceptionTest(NullPointerException.class)
public static void doublyBad() { ... }
总结:当可以使用注解代替时,没有理由使用命名模式。所有程序员都应该使用 Java 提供的预定义注解类型。