J2SE 5.0提供了很多新的特性。其中的一个很重要的特性,就是对元数据(Metadata)的支持。在J2SE5.0中,这种元数据叫作注释(Annotation)。通过使用注释, 程序开发人员可以在不改变原有逻辑的情况下,在源文件嵌入一些补充的信息。代码分析工具,开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。举个例子,比如说你希望某个方法的参数或者返回值不为空,虽然我们可以在Java doc中说明,但是表达同样意思的说法有很多,比如"The return value should not be null"或者"null is not allowed here"。测试工具很难根据这些语言来分析出程序员所期望的前提条件(Pre-condition)和执行后的条件(Post-condition)。 而使用注释(Annotation),这个问题就可以轻而易举的解决了。
public abstract class BaseClass{ //模板方法的基类 public void doWork(){ doPartI(); //先调用doPartI()方法 doPartII();//之后调用doPartII()方法 } public abstract void doPartI(); public void doPartII(){} } public class SubClass extend BaseClass{ public void doPartI(){}; @Override public void doPortII(){//拼写错误,产生编译错误 System.out.println("override the method of superclass"); } } 图4 Override应用的例子 3) 注释的注释
public class MyCalculator { boolean isReady; @TOFORMATE double concurrency; @TOFORMATE Date debitDate; public MyCalculator() { super(); }
@TODO public void calculateRate(){ System.out.println("Calculating..."); } } 清单15动态查找注释
public class TestCalculator { public static void main(String[] args) { MyCalculator cal = new MyCalculator(); cal.calculateRate(); try { Class c = cal.getClass(); Method[] methods = c.getDeclaredMethods();
for (Method m: methods) { // 判断这个方法有没有使用TODO if (m.isAnnotationPresent(TODO.class)) System.out.println("Method "+m.getName()+": the TODO is present"); }
Field[] fields = c.getDeclaredFields(); for (Field f : fields) { // 判断这个域有没有使用TOFORMATE if (f.isAnnotationPresent(TOFORMATE.class)) System.out.println("Field "+f.getName()+": the TOFORMATE is present"); } } catch (Exception exc) { exc.printStackTrace(); } } } 下面我们来运行这个例子,这个例子的运行结果如图10所示。
图7 使用Vistor模式实现格式输出 在这里我们定义了一个Exporter抽象类,我们可以通过继承Exporter类,重写其visit方法来实现不同格式的文件输出。图11种给出visit方法的实现是一个简单的例子。如果要实现输出成XML格式的,可以定义Exporter子类:XMLExporter。如果希望输出成文本的可以定义TXTExporter。但是这样做不够灵活的地方在于,如果Employee加入其他的域变量,那么相应的visitor类也需要进行修改。这就违反了面向对象Open for Extension, close for Modification的原则。