effective-java学习笔记---注解优于命名模式39

effective-java学习笔记---注解优于命名模式39

命名模式的缺点有以下三点:(在第 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 提供的预定义注解类型。