一、什么是注释 | |
假设有两个类Class1和ParentClass1,用Class1中的myMethod1方法覆盖ParentClass1中的myMethod1方法。
class ParentClass1 ...{ public void myMethod1() ...{...} } class Class1 extends ParentClass1 ...{ public void myMethod2() ...{...} } 建立Class1的实例,并且调用myMethod1方法
ParentClass1 c1 = new Class1(); c1.myMethod1(); 以上的代码可以正常编译通过和运行。但是在写Class1的代码时,误将myMethod1写成了myMethod2,然而在调用时,myMethod1并未被覆盖。因此,c1.myMethod1()调用的还是ParentClass1的myMethod1方法。更不幸的是,程序员并未意识到这一点。因此,这可能会产生bug。
class Class1 extends ParentClass1 ...{ @Override // 编译器产生一个错误 public void myMethod2() ...{...} } 以上代码编译不能通过,被Override注释的方法必须在父类中存在同样的方法程序才能编译通过。也就是说只有下面的代码才能正确编译。
class Class1 extends ParentClass1 ...{ @Override public void myMethod1() ...{...} } Deprecated 这个注释是一个标记注释。所谓标记注释,就是在源程序中加入这个标记后,并不影响程序的编译,但有时编译器会显示一些警告信息。
class Class1 ...{ @Deprecated public void myMethod()...{} } class Class2 extends Class1 ...{ public void myMethod()...{} } 1 1 运行javac test.java 出现如下警告:
public void myMethod() ...{ List wordList = new ArrayList(); wordList.add("foo"); } 这是一个类中的方法。编译它,将会得到如下的警告。 1 public void myMethod() 三、如何自定义注释
public @interface MyAnnotation ...{ } 上面的代码是一个最简单的注释。这个注释没有属性。也可以理解为是一个标记注释。就象Serializable接口一样是一个标记接口,里面未定义任何方法。
public @interface MyAnnotation ...{ String value(); } 可以按如下格式使用MyAnnotation
@MyAnnotation("abc") public void myMethod() ...{ } 看了上面的代码,大家可能有一个疑问。怎么没有使用value,而直接就写”abc”了。那么”abc”到底传给谁了。其实这里有一个约定。如果没有写属性名的值,而这个注释又有value属性,就将这个值赋给value属性,如果没有,就出现编译错误。
public @interface MyAnnotation ...{ public String myMethod()...{} default “xyz”; } 可以直接使用MyAnnotation
@MyAnnotation // 使用默认值xyz public void myMethod() ...{ } 也可以这样使用
@MyAnnotation(myMethod=”abc”) public void myMethod() ...{ }
public @interface MyAnnotation ...{ public enum MyEnum...{A, B, C} public MyEnum.value1() ...{} public String value2() ...{} } @MyAnnotation(value1=MyAnnotation.MyEnum.A, value2 = “xyz”) public void myMethod() ...{ } 这一节讨论了如何自定义注释。那么定义注释有什么用呢?有什么方法对注释进行限制呢?我们能从程序中得到注释吗?这些疑问都可以从下面的内容找到答案。 1
@Target(...ElementType.METHOD) @interface MyAnnotation ... {} @MyAnnotation // 错误的使用 public class Class1 ... { @MyAnnotation // 正确的使用 public void myMethod1() ...{} } 以上代码定义了一个注释MyAnnotation和一个类Class1,并且使用MyAnnotation分别对Class1和myMethod1进行注释。如果编译这段代码是无法通过的。也许有些人感到惊讶,没错啊!但问题就出在@Target(ElementType.METHOD)上,由于Target使用了一个枚举类型属性,它的值是ElementType.METHOD。这就表明MyAnnotation只能为方法注释。而不能为其它的任何语言元素进行注释。因此,MyAnnotation自然也不能为Class1进行注释了。
@Target(...{ElementType.METHOD, ElementType.CONSTRUCTOR}) @interface MyAnnotation ... {}Retention
@Retention(RetentionPolicy.SOURCE) @interface MyAnnotation1 ...{ } @Retention(RetentionPolicy.CLASS) @interface MyAnnotation2 ...{} @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation3 ...{} 其中第一段代码的作用是不将注释保存在class文件中,也就是说象“//”一样在编译时被过滤掉了。第二段代码的作用是只将注释保存在class文件中,而使用反射读取注释时忽略这些注释。第三段代码的作用是即将注释保存在class文件中,也可以通过反射读取注释。
@interface MyAnnotation...{ } @MyAnnotation class Class1 ... { public void myMethod() ...{ } }使用javadoc为这段代码生成文档时并不将@MyAnnotation包含进去。生成的文档对Class1的描述如下:
class Class1extends java.lang.Object 而如果这样定义MyAnnotation将会出现另一个结果。 @Documented @interface MyAnnotation ...{} 生成的文档: @MyAnnotation // 这行是在加上@Documented后被加上的 class Class1extends java.lang.Object Inherited
@Inherited @interface MyAnnotation ...{ } @MyAnnotation public class ParentClass ...{} public class ChildClass extends ParentClass ...{ } 在以上代码中ChildClass和ParentClass一样都已被MyAnnotation注释了。 五、如何使用反射读取注释
Method method = TestAnnotation.class.getMethod("myMethod", null); Annotation annotation = method.getAnnotation(MyAnnotation.class); 注:要想使用反射得到注释信息,这个注释必须使用 @Retention(RetentionPolicy.RUNTIME)进行注释。 总结 |
http://www.cnblogs.com/liubiqu/archive/2008/06/01/1211503.html