Java提供了一项可以在源文件中嵌入附加信息的功能,这些信息称为注解(annotation),他们不会改变程序的运行.但是,这些信息在开发和部署期间可以由许多工具使用.例如,注解可以由源代码生成器,编译器或部署工具处理.虽然元数据(metadata)这个术语也用来指示这项功能,但是术语”注解”的描述性更好,并且更加常用.
注解是一个庞大复杂的话题,这里仅做简要讨论,以便熟悉其概念.
注解通过基于interface的机制创建,如下所示:
@interface MyAnno { String str(); int val(); }
上述语句声明了一个名为MyAnno的注解.注意interface关键字前有一个@,他告诉编译器此处声明了一个注解.接下来,注意两个成员str()和val().所有注解都仅由方法声明组成.但是不能提供方法主体,而是由Java来实现这些方法 .这些方法实际上就像域一样.
所有的注解类型都自动的扩展了Annotation接口.因此,Annotation是所有注解的超接口,他在java.lang.annotaition包中声明.
起初,注解仅用来标注声明.这样使用他时,任何类型的声明都可以有ige与之相关的注解.例如,类,方法,域,形参和enum常量都可以有注解.甚至注解还可以带有注解.在上述所有情况下,注解都位于其余声明部分之前.从JDK8开始,也可以对类型用法(type use)进行注解,如强制转换类型或方法返回类型.
使用注解之后,需要向其成员提供值.例如,下面是一个应用于方法的MyAnno示例:
@MyAnno (str = "Annotation Example",val=100) @interface MyAnno
该注解与方法MyAnno()链接,下面仔细分析一下注解的语法.注解名前置了@,后面跟成员初始值的括号列表.为了给成员提供值,需要向成员名赋值.因此,该例中字符串”Annotation Example”赋值非了MyAnno的str成员.注意该赋值语句中str后面没有跟括号.当为注解成员提供值时,只使用其名称.因此,在本例中注解成员就像域一样.
Java定义了许多内置注解,大多数是专用的,有9个是通用的.下面的4个从java.lang.annotation导入:@Retention,@Documented,@Target和@Inherited.下面的5个包括在java.lang中:@override,@Deparecated,@SfaeVarargs,@FunctionalInterface和@suppressWarnings,下表列出了这些内置注解:
注解
|
说明
|
@retention
|
指定与注解相关联的保持策略.保持策略确定注解在编译和部署过程中保持多久
|
@Documented
|
标记注解,告诉工具注解被文档化,他只用作注解声明的注解
|
@Target
|
指定应用注解的声明的类型,他只用作另一个注解的注解.@Target有一个实参,他必须是来自ElementType枚举的常量,该枚举定义各种常量,如CONSTRUCTOR,FLELD和METHOD等.该实参确定应用注解的声明的类型,如果没有指定@Target,对任何声明就不能使用注解.
|
@Inherited
|
标记注解,让超类的注解由子类继承
|
@Override
|
标记注解,使用@override注解标记的方法必须重写来自超类的方法,否则将导致编译时错误.这样做可以确保超类方法被重写而不是被重载.
|
@Deprecated
|
标记注解,指示一个声明已经过时,已被新形式取代
|
@SafeVarargs
|
标记注解,表示没有与方法或构造函数的课表长度形参有关的不安全动作发生.只能用于static或final方法或构造函数
|
@SuppressWarnings
|
指定由编译器发出的一条或多条警告将禁止.要禁止的警告通过字符串形式的名称指定
|
@FunctionalInterface
|
标记注解,用来注解接口声明.指示被注解的接口是一个函数式接口,该接口包含且仅包含一个抽象方法,可以通过lambda表达式来使用函数式接口.@FunctionalInterface是纯信息式的,理解这一点很重要,根据定义,任何包含且仅包含一个抽象方法的接口都是函数式接口.
|
注意:在java.lang.annotation中,JDK8新增了两个注解:@Repeatable和@Native.其中@Repeatable支持重复的注解,可以将这些注解多次应用到某一个声明.@Native用于注解可执行代码(即本机代码)所访问的常量域.这两个注解都是专用注解.
下面是一个使用@Deprecated注解标记MyClass类和getMsg()方法的示例.当编译该程序时,将会警告使用了这些不再建议使用的元素.
public class test2 { // @param args public static void main(String args[]) { MyClass obj = new MyClass("test"); } } @Deprecated class MyClass { private String msg; MyClass(String m) { msg = m; } }