1. Annotation对程序运行没有影响,它的目的在于对编译器或分析工具说明程序的某些信息,您可以在包、类、方法、域成员等加上Annotation。每个Annotation对应于一个实际的Annotation类型。
2. 限定Override父类方法@Override
java.lang.Override是J2SE 5.0中标准的Annotation类型之一,它对编译器说明某个方法必须是重写父类中的方法。编译器得知这项信息后,在编译程序时如果发现被@Override标示的方法并非重写父类中的方法,就会报告错误。
如下例:
package ysu.hxy;
public class CustomClass
{
@Override
public String ToString()
{
return "customObject";
}
}
编译时会报告错误:
D:\Java_Test>javac -d . CustomClass.java
CustomClass.java:5: 方法未覆盖其父类的方法
@Override
^
1 错误
这就是java.lang.Override这个Annotation类型的作用。如果这里不没有@Override,则此类编译时并不会出现任何的错误,编译器不会知道是想重写toString()方法,只会以为是定义了一新的ToString()方法。将此倒中ToString()方法改为toString()方法编译时就不用有问题了。
2. java.lang.Override是一个Marker Annotation,就是用于标示的Annotation。Annotation类型与Annotation实际上是有区分的,Annotation是否Annotation类型的实例。例如@Override是个Annotation,它是java.lang.Override类型的一个实例,一个文件中可以有很多个@override,但它们都是属于java.lang.Override类型。
3. 标示方法为Deprecated @Deprecated:
java.lang.Deprecated是J2SE5.0中标准的Annotation类型之一,它对编译器说明某个方法已经不建议使用。如果有开发人员试图使用或者重写被@Deprecated标示的方法,编译器必须提出警告信息。
package ysu.hxy;
public class Something
{
//使用@Deprecated 为getSomething()方法加上标示
@Deprecated public Something getSomething()
{
return new Something();
}
}
如果有人试图在继承这个类后重写或者在程序中调用getSomething()方法,则编译时会有警告出现。如下所示:
package ysu.hxy;
public class SomethingDemo
{
public static void main(String[] args)
{
Something some = new Something();
//调用被@Deprecated标示的方法
some.getSomething();
}
}
编译时会出现以下警告:
D:\Java_Test>javac -d . SomethingDemo.java
注意:SomethingDemo.java 使用或覆盖了已过时的 API。
注意:要了解详细信息,请使用 -Xlint:deprecation 重新编译。
java.lang.Deprecated也是一个Marker Annotation,简单地说就是用于标示。
4. 抑制编译器警告@SuppressWarnings
java.lang.SuppressWarnings是J2SE5.0中标准的Annotations类型之一,它对编译器说明某个方法中若有警告信息,则加以抑制,不用在编译完成后出现警告。使用方式参见下面简单示例:
package ysu.hxy;
import java.util.*;
public class SomeClass2
{
@SuppressWarnings(value=("unchecked"))
public void doSomething()
{
Map map = new HashMap();
map.put("some","thing");
}
}
理论上是可以抑制警告的,你也可以指定忽略多个警告:如
@SuppressWarnings(value={"unchecked","deprecation"});
不过在JDK 5.0上并没有实现这个Annotation的功能,所以@SuppressWarnings实际上并没有作用。如果真要关掉警告,那么在编译时加上-nowarn是另一个方法,只不过这会关掉所有的警告信息。
@SuppressWarnings是所谓的Single-Value Annotation,因为这样的Annotation只有一个成员,称为value成员,可在使用Annotation时作额外的信息指定。
5. 自定义Annotation类型:
要定义一个Annotation所需的动作,就类似于定义一个接口,只不过使用的是@interface,如下范例:
package ysu.hxy;
public @interface Debug{}
由于是一个Marker Annotation,所以没有任何成员在Annotation定义中。编译完成后就可以在程序代码中使用这个Annotation。例如:
public class SomeObject
{
@Debug
public void doSomething()
{
//...
}
}
稍后将看到如何在程序中获得Annotation信息,接着来看看如何定义一个Single-Annotation,它只有一个value成员,如下:
package ysu.hxy;
public @interface UnitTest
{
String value();
}
实际上定义了value()方法,编译器在编译时会自动产生一个value的域成员,接着在使用UnitTest Annotation时要指定值,如:
public class MathTool
{
@UnitTest("GCD");
public static int gcdOf(int num1,int num2)
{
//...
}
}
@UnitTest("GCD")实际上是 @UnitTest(value="GCD")的简便写法,value也可以是数组值。例如定义一个FunctionTest的Annotation类型。
package ysu.hxy;
public @interface FunctionTest
{
String[] value();
}
在使用此段代码定义的Annotation时,可以写成@Functiontest({"method1","method2"})这样的简便形式,或是
@Functiontest(value={"method1","method2"}) 这样的详细形式,也可以对value成员设定默认值,使用default关键词即可。
package ysu.hxy;
public @interface UnitTest2
{
String value() default "noMethod";
}
这样如果使用@UnitTest2时没有指定value值,则value默认就是noMethod。
也可以为Annotation定义额外的成员,以提供额外的信息给分析工具。如下例定义使用枚举类型、String与booean类型来定义Annotation的成员。
package ysu.hxy;
public @interface Process
{
public enum Current {NONE,REQUIRE,ANALYSIS,DESIGN,SYSTEM};
Current current() default Current.NONE;
String tester();
boolean ok();
}
可以用如下的代码来使用这个范例定义Annotation的成员。
package ysu.hxy;
public class Application
{
@Process
(
current = Process.Current.ANALYSIS,
tester = "Justin Lin",
ok = true
)
public void doSomething()
{
//....
}
}
当使用@interface自行定义Annotation类型时,实际上是自动继承了java.lang.annotation.Annotation接口,并由编译器自动完成其他产生的细节,并且在定义Annotation类型时,不能继承其他的Annotation类型或接口。定义Annotation类型时也可以使用包机制来管理类,如果在别的包下使用自定义的Annotation,记得使用import告诉编译器类型的包位置。例如:
import ysu.hxy.Debug;
public class Test
{
@Debug
public void doTest()
{
}
}
或是使用完整的Annotation名称, 例如:
public class Test
{
@ysu.hxy.Debug
public void doTest()
{
}
}