注解,元数据的一种形式,提供关于程序不是程序自己的一部分数据。注解对代码的操做没有直接影响。
注解有多用途,如:
a、用于编译信息。经过编译器检测错误or抑制警告
b、编译时和部署时的处理。软件工具可以处理注解信息生成代码,xml文件等
c、运行时的处理。一些注解能够在运行时被检查
一、注解基础
注解的格式
最简单的形式如:@Entity
@:指明编译器下面是一个注解
下面注解名称是Override
@Override
void mySuperMethod() {…}
注解能够包含带名称or不带名称,及这些元素的值,如
@Author(
name=”Benjamin Franklin”
date=”3/27/2003”
)
class MyClass(){...}
或
@SuppressWarnings(value=“unchecked”)
void myMethod(){...}
若此时只有一个元素value时,该元素名称能够忽略,如:
@SuppressWarnings(“unchecked”)
void myMethod(){...}
若该注解没有元素时,那圆括号能够忽略,如@Override例子
能够在同一个声明处使用多个注解
@Author(name = "Jane Doe")
@EBook
class MyClass(){...}
若注解有相同的类型,称为重复注解,目前只有java SE8 支持,如:
@Author(name = "Jane Doe")
@Author(name = "John Smith")
class MyClass(){...}
注解类型能够是Java SE API的java.lang或java.lang.annotation包中定义的类型,前面例子中 SuppressWarnings和Override都时预约义java注解。你也可自定义注解类型。Author和EBook为自定义注解类型
注解的使用
注解能够用于:类的声明,字段,方法,和其余的程序元素。
因Java SE8的发布,注解也能够应用于类型的使用,如:
a、类实例的建立表达式
new @Interned MyObject();
b、类型转换
myString = (@NonNull String)str;
c、implements 从句
class UnmodifiablleList<T> implements
@Readonly List<@Readonly T> {...}
d、抛出异常的声明
void monitorTemperature() throws
@Critical TemperatureException {...}
二、声明一个注解类型
大多数注解替换代码中的注释
假如某个软件集团在每一个类的开始使用注释提供重要信息:
public class Generation3List extends Generation2List {
// Author: John Doe
// Date: 3/17/2002
// Current revision: 6
// Last modified: 4/12/2004
// By: Jane Doe
// Reviewers: Alice, Bill, Cindy
// class code goes here
}
使用注解来添加这些相同的元数据,你必须首先定义注解类型,如:
@interface ClassPreamble {
String author();
String date();
int currentRevision() default 1;
String lastModified() default "N/A";
String lastModifiedBy() default "N/A";
// Note use of array
String[] reviewers();
}
注解类型的定义相似于接口定义,只是在关键字interface 以前添加@符号。注解类型是一种接口形式,上面注解定义包含注解类型的元素声明,看起来很像方法,注意:它们有可选的默认值。
注解类型定义完成后,你可使用相应元素值填充后使用该注解,如:
@ClassPreamble (
author = "John Doe",
date = "3/17/2002",
currentRevision = 6,
lastModified = "4/12/2004",
lastModifiedBy = "Jane Doe",
// Note array notation
reviewers = {"Alice", "Bob", "Cindy"}
)
public class Generation3List extends Generation2List {
// class code goes here
}
注意:使 @ClassPreamble的信息出如今javadoc生成的文档中,你必须在定义 @ClassPreamble时使用@Documented,如:
@Documented
@interface ClassPreamble {
// Annotation element definitions
}
三、预约义的注解类型
Java SE API中预约义注解集。一些经过编译器被使用,一些提供给其余注解。
由java语言使用的注解类型
a、@Deprecated:指明标记元素已废弃,应再也不使用。当程序中的方法、类、字段使用@Deprecated时,编译器会生成一个警告。当一个元素被废弃,它也应该在javadoc中记录废弃@deprecated标签,注意javadoc中的d为小写,如:
// Javadoc comment follows
/**
* @deprecated
* explanation of why it was deprecated
*/
@Deprecated
static void deprecatedMethod() { }
}
b、@Override:指明编译器该元素是覆盖父类中声明的元素,如:
// mark method as a superclass method
// that has been overridden
@Override
int overriddenMethod() { }
重写方法不是必需要求该标注,但它有助于防止错误,若一个方法标记@Override识别,编译器会生成一个正确重写父类中一个方法的错误。
c、@SuppressWarnings:指明编译器抑制特定的警告信息,不然会生成一个警告,下面使用一个废弃的方法,编译器一般会生成一个警告,使用该注解来抑制该警告。
// use a deprecated method and tell
// compiler not to generate a warning
@SuppressWarnings("deprecation")
void useDeprecatedMethod() {
// deprecation warning
// - suppressed
objectOne.deprecatedMethod();
}
每一个编译器警告属于一类,java规范列出2类:deprecation和unchecked。unckecked警告会在接口与写传统代码(泛型以前)发生,为了抑制多个类别的警告,可以使用:
@SuppressWarnings({"unchecked", "deprecation"})
d、@SafeVarargs:适用于方法or构造器,断言代码不执行潜在不安全的操做在它的Varargs参数上,当使用该注解时,关于Varargs使用unchecked警告将抑制。
e、@FunctionalInterface:Java SE 8引入,声明一个由java 语言定义的函数接口
提供给其余注解的类型
注解能够提供给另外注解,称元注解,在java.lang.annotation包中定义以下元注解
a、@Retention:指明如何存储注解:
RetentionPolicy.SOURCE只保留在源代码级别,被编译器忽略
RetentionPolicy.CLASS保留在编译时,但被JVM忽略
RetentionPolicy.RUNTIME保留在JVM,所依经过运行环境使用
b、@Docmented:指明该元素应该使用javadoc工具进行归档,默认,注解在javadoc中是不被包含的。
c、@Target:指明另外一个注解限制使用java元素注解能够应用,目标注解指定一个下面的元素类型的值。
ElementType.ANNOTATION_TYPE应用与注释类型
ElementType.CONSTRUCTOR、ElementType.FIELD、ElementType.LOCAL_VARIABLE、ElementType.METHOD、ElementType.PACKAGE、ElementType.PARAMETER、ElementType.TYPE
d、@Inherited:指明该注解类型能够从父类继承,只适用于类声明的注解
e、@Repeatable:Java SE 8引入,代表注解能够不止一次应用到相同的声明or类型的使用
四、类型注解和可插拔式系统
Java SE8以前,注解仅能应用与声明部分,Java SE 8发布后,注解也能够应用于任何类型使用的地方,这种形式的注解称为类型注解。
类型注解是用来支持并提升java程序的分析方法,确保更强的类型检查。Java 8发布没有提供类型检查的框架,但它容许你写or下载一个类型检查的框架,实现为一个or多个插件可插拔式模块中使用java编译器的结合。
如,你想确保程序中某个特定变量不被设置为null;避免NullPointerException。你能够编写一个自定义插件来检查它。你能够修改特定变量的代码注解,代表它是不为null,如:
@NonNull String str;
当编译代码时,在命令行包含NonNull,编译器检测可能的问题并打印一个警告,容许你修改代码避免这个错误。
五、可重复注解
java 8发布后,容许你在声明or类型使用时不止一次使用相同注解。
例如,编写一个操做计时器服务,在给定一个时间or一个定义的调度器上运行一个方法。如今你设置计时去运行方法doPeriodicCleanup,在每月的最后一天和每周五的pm 11点,如:
@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }
为了兼容,可重复注解存储java编译器自动生成一个注解容器中,为实现编译器,你代码须要2个声明要求:
a、声明一个可重复的注解类型
注解类型必须使用@Repeatable元注解标注,如
@Repeatable(Schedule.class)
public @interface Schedule { ... }
b、声明包含注解的类型
包含注解必须有一个使用一个数组类型的元素值,数组类型必须是一个可重复注解类型。如:
public @interface Schedules {
Schedule[] value;
}
java