现在的位置: 首页 > 综合 > 正文

来自另一篇Java Annotation文章

2013年10月29日 ⁄ 综合 ⁄ 共 4870字 ⁄ 字号 评论关闭

 

第一个Annotation例子
Example to Define an Annotation (Annotation type)
public @interface MyAnnotation {
   String doSomething();
}
Example to Annotate Your Code (Annotation)
MyAnnotation (doSomething="What to do")
public void mymethod() {
   ....
}
三种annotation types
  • Marker:只有annotation name,里面没有任何eleme.
Example:
public @interface MyAnnotation {
}
Usage:
 @MyAnnotation
public void mymethod() {
                ....
        }
  • Single-Element:只有一个element,或者说只有一个value type
Example:
public @interface MyAnnotation
{
    String doSomething();
}
Usage:
@MyAnnotation ("What to do")
public void mymethod() {
   ....
}
  • Full-value or multi-value: annotation包含了多个element,或者说包含了多个value.
Example:
public @interface MyAnnotation {
   String doSomething();
   int count;
String date();
}
Usage:
@MyAnnotation (
         doSomething="What to do",
         count=1,
         date="09-09-2005")
public void mymethod() {
   ....
}
 
定义一个Annotation的规则
  1. 以@开头 + interface keywork,然后跟着是你的annotation name.
  2. 方法的声明不能够加任何参数
  3. 方法的声明不能够有throws抛出异常的语句
  4. 方法的返回值类型必须是以下几种:
    • primitives
    • String
    • Class
    • enum
    • array of the above types

JDK 5有一些内置的annotations,从功能上划分,有2种内置annotations

  • Simple annotations: JDK 5已经内置帮你定义好的annotations,可以直接使用到你的代码上。这类annotation目前只有3个: Override, Deprecated, Suppresswarnings
  • Meta annotations: 只能使用在自定义的annotation的声明处(注意:只能用在声明处,不能用在使用处,见下面例子)。因此这类annotations也称为注解的注解。 这类annotation目前有4个:Target, Retention, Documented, Inherited

 

Override annotation

一个marker annotation,用来标注方法。它用来表示被标注的方法重载了父类的方法,起到了断言的作用。如果我们使用了这种annotation在一个没有覆盖父类方法的方法时,java编译器将以一个编译错误来警示。
这个annotaton常常在我们试图覆盖父类方法而确又写错了方法名时发挥威力。使用方法极其简单:只要在被修饰的方法前面加上@Override。

Example

public class Test_Override {
  @Override
  public String toSring() { // 注意:方法名拼写错了,编译器会报错
    return super.toString() +
       " Testing annotation name: 'Override'";
  }
}

Deprecated annotation

 也是一个marker annotation。表示不鼓励使用这个被标注的程序元素。而且这种修饰具有一定的“延续性”:如果我们在代码中通过继承或者覆盖的方式使用了这个过时的类型或者成员,虽然继承或者覆盖后的类型或者成员并不是被声明为@Deprecated,但编译器仍然要报警。

值得注意,@Deprecated这个annotation类型和javadoc中的@deprecated这个tag是有区别的:前者是java编译器识别的,而后者是被javadoc工具所识别用来生成文档(包含程序成员为什么已经过时、它应当如何被禁止或者替代的描述)。

在java5.0,java编译器仍然象其从前版本那样寻找@deprecated这个javadoc tag,并使用它们产生警告信息。但是这种状况将在后续版本中改变,我们应在现在就开始使用@Deprecated来修饰过时的方法而不是@deprecated javadoc tag。

Example

public class Test_Deprecated {
   @Deprecated
   public static void doSomething() {
      System.out.println("Testing annotation name: 'Deprecated'");
   }
}
public class Test{
   public void test(){
  Test_Deprecated.doSomething();
   }
}

那么在compile到Test_Deprecated.doSomething();时会出现deprecated warning

Suppresswarnings annotation

@SuppressWarnings被用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告。在java5.0,sun提供的javac编译器为我们提供了-Xlint选项来使编译器对合法的程序代码提出警告,此种警告从某种程度上代表了程序错误。例如当我们使用一个generic collection类而又没有提供它的类型时,编译器将提示出"unchecked warning"的警告

通常当这种情况发生时,我们就需要查找引起警告的代码。如果它真的表示错误,我们就需要纠正它。例如如果警告信息表明我们代码中的switch语句没有覆盖所有可能的case,那么我们就应增加一个默认的case来避免这种警告。
相仿,有时我们无法避免这种警告,例如,我们使用必须和非generic的旧代码交互的generic collection类时,我们不能避免这个unchecked warning。此时@SuppressWarning就要派上用场了,在调用的方法前增加@SuppressWarnings修饰,告诉编译器停止对此方法的警告。
SuppressWarning不是一个marker annotation。它有一个类型为String[ ]的成员,这个成员的值为被禁止的警告名。对于javac编译器来讲,被-Xlint选项有效的警告名也同样对@SuppressWarings有效,同时编译器忽略掉无法识别的警告名。

那么下面这个例子就是对上面使用@Deprecated的例子进行警告避免

Example

public class Test{
  @SuppressWarnings({"deprecation"})    
  public void test(){ 
  Test_Deprecated.doSomething();
  } 
}
更多的关于@SuppressWarnings的例子:
@SuppressWarnings(value={"unchecked","fallthrough"})
public void lintTrap() { /* sloppy method body omitted */ }
在这个例子中SuppressWarnings annotation类型只定义了一个单一的成员,所以只有一个简单的value={...}作为name=value对。又由于成员值是一个数组,故使用大括号来声明数组值。
注意:我们可以在下面的情况中缩写annotation:当annotation只有单一成员,并成员命名为"value="。这时可以省去"value="。比如将上面的SuppressWarnings annotation进行缩写:
@SuppressWarnings({"unchecked","fallthrough"})
如果SuppressWarnings所声明的被禁止警告个数为一个时,可以省去大括号
@SuppressWarnings("unchecked")
  
Target annotation
在某个自定义注解声明中使用target annotation,表明该自定义注解能使用到什么地方。它可以指明下面几个地方
  • @Target(ElementType.TYPE)—表明该自定义注解可以使用到任何地方
  • @Target(ElementType.FIELD)—表明该自定义注解只能使用在field的声明上
  • @Target(ElementType.METHOD)—表明该自定义注解只能使用在方法声明上
  • @Target(ElementType.PARAMETER)—表明该自定义注解只能使用在方法的参数上
  • @Target(ElementType.CONSTRUCTOR)—表明该自定义注解只能使用在构造方法上
  • @Target(ElementType.LOCAL_VARIABLE)—表明该自定义注解只能使用在local variable上
  • @Target(ElementType.ANNOTATION_TYPE)—indicates that the declared type itself is an annotation type
 

Example

首先,定义一个annotation named Test_Target with @Target:

@Target(ElementType.METHOD)
public @interface Test_Target {
   public String doTestTarget();
}
 

然后使用Test_Target annotation:

 public class TestAnnotations {
   public static void main(String arg[]) {
      new TestAnnotations().doTestTarget();
   }
   @Test_Target(doTestTarget="Hello World !")
   public void doTestTarget() {
      System.out.printf("Testing Target annotation");
   }
}

由于Test_Target annotation使用了@Target(ElementType.METHOD),则表示Test_Target annotation只能使用在方法上

那么上面的代码是对的,但下面的代码会报错,因为Test_Target annotation使用在一个variable上,编译时就会报错:

public class TestAnnotations {
   @Test_Target(doTestTarget="Hello World !")
   private String str;
   public static void main(String arg[]) {
      new TestAnnotations().doTestTarget();
   }
   public void doTestTarget() {
      System.out.printf("Testing Target annotation");
   }
}

抱歉!评论已关闭.