简介
解释何为注解的最佳方式就是元数据这个词:描述数据自身的数据。 注解就是代码的元数据,他们包含了代码自身的信息,是一种代码级别的说明。 它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。 它可以声明在包、类、字段、方法、局部变量、方法参数等的前面, 用来对这些元素进行说明,注释。
注解可以被用在包,类,方法,变量,参数上。 自Java8起,有一种注解几乎可以被放在代码的任何位置,叫做类型注解。 被注解的代码并不会直接被注解影响。这只会向第三系统提供关于自己的信息以用于不同的需求。 注解可以被编译至class文件中,而且会在运行时被处理程序提取出来用于业务逻辑。 当然,创建在运行时不可用的注解也是可能的,甚至可以创建只在源文件中可用, 在编译时不可用的注解。
获取注解信息的时候,是根据类的Class信息来获取,不需要有对象实例, 不方便的地方在于,使用注解的时候注解元素内容要在编译之前就要确定, 不能够进行动态赋值。
规范
最基本的注解形式如下:
@Entity
上面的 @
字符表示告知编译器后面跟的是一个注解,Entity
是注解的名称。最常见的比如表示 覆写的Override注解:
@Override
void mySuperMethod() { ... }
使用注解有如下几种方式:
- 注解可以不包括元素内容,一般用作标记
- 注解包含元素内容的时候,如果只有一个元素,可以省略元素名称
- 可以多个注解同时标注在同一个类(变量/方法等)上
- Java8中支持重复注解(Repeating Annotations)
// 没有元素
@Override
void mySuperMethod() { ... }
// 省略name
@SuppressWarnings(value = "unchecked")
void myMethod() { ... }
@SuppressWarnings("unchecked")
void myMethod() { ... }
// 多个元素
@Author(
name = "Benjamin Franklin",
date = "3/27/2003"
)
class MyClass() { ... }
// 多个注解(multiple annotations)
@Author(name = "Jane Doe")
@EBook
class MyClass { ... }
// Repeating annotations
@Author(name = "Jane Doe")
@Author(name = "John Smith")
class MyClass { ... }
用途
注解有很多用途,比如:
- 提供编译器所需信息:编译器可以用使用注解来检测错误或忽略警告信息
- 编译期间或者部署期间:可使用注解生成代码,XML文件等
- 运行期间:一些注解可在运行期间执行
Java之后开始支持类型注解:
// Class instance creation expression:
new @Interned MyObject();
// Type cast:
myString = (@NonNull String) str;
// implements clause:
class UnmodifiableList<T> implements @Readonly List<@Readonly T> { ... }
// Thrown exception declaration:
void monitorTemperature() throws @Critical TemperatureException { ... }
预定义注解
预定义注解有两类,一类是可以直接用于程序代码的注解,另一个是用于定义注解时的注解。
第一类注解,java.lang 包下:
@Deprecated
@Override
@SuppressWarnings
@SafeVarargs
@FunctionalInterface
第二类注解,java.lang.annotation 包下,称为元注解(meta-annotations):
@Retention
表示注解被如何存储,有如下三个可选项:RetentionPolicy.SOURCE
源码级,被编译器忽略RetentionPolicy.CLASS
文件级,编译期间有效,被JVM忽略RetentionPolicy.RUNTIME
运行期,一直到运行期间都有效
@Documented
可被 Javadoc tool 工具调用@Target
注解可被用于何处:ElementType.ANNOTATION_TYPE
注解类ElementType.CONSTRUCTOR
构造器ElementType.FIELD
变量ElementType.LOCAL_VARIABLE
本地变量ElementType.METHOD
方法ElementType.PACKAGE
包ElementType.PARAMETER
参数ElementType.TYPE
Java类
@Inherited
是否可被子类继承@Repeatable
是否支持Repeat
使用范例
定义一个类注解CustomClassAnnotation
,一个方法注解CustomMethodAnnotation
, 然后在 AnnotatedTest
类中使用此注解,在 TestMain
方法中获取注解内容:
/**
* CustomClassAnnotation Created by Bob on 2016/9/28.
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CustomClassAnnotation {
String author() default "danibuiza";
String date();
}
/**
* CustomMethodAnnotation Created by Bob on 2016/9/28.
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CustomMethodAnnotation {
String author() default "danibuiza";
String date();
String description();
}
/**
* AnnotatedTest Created by Bob on 2016/9/28.
*/
@CustomClassAnnotation(date = "2016-09-28")
public class AnnotatedTest {
@CustomMethodAnnotation(date = "2014-06-05", description = "annotated method")
public String annotatedMethod() {
return "nothing niente";
}
@CustomMethodAnnotation(author = "friend of mine", date = "2014-06-05", description = "annotated method")
public String annotatedMethodFromAFriend() {
return "nothing niente";
}
}
/**
* TestMain Created by Bob on 2016/9/28.
*/
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class TestMain {
public static void main(String[] args) throws Exception {
Class<AnnotatedTest> object = AnnotatedTest.class;
// Retrieve all annotations from the class
Annotation[] annotations = object.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// Checks if an annotation is present
if (object.isAnnotationPresent(CustomClassAnnotation.class)) {
// Gets the desired annotation
Annotation annotation = object.getAnnotation(CustomClassAnnotation.class);
CustomClassAnnotation customClassAnnotation = (CustomClassAnnotation) annotation;
String author = customClassAnnotation.author();
String date = customClassAnnotation.date();
System.out.println(customClassAnnotation + " => " + author + ", " + date);
}
// the same for all methods of the class
for (Method method : object.getDeclaredMethods()) {
if (method.isAnnotationPresent(CustomMethodAnnotation.class)) {
Annotation annotation = method.getAnnotation(CustomMethodAnnotation.class);
CustomMethodAnnotation customMethodAnnotation = (CustomMethodAnnotation) annotation;
String author = customMethodAnnotation.author();
String date = customMethodAnnotation.date();
String description = customMethodAnnotation.description();
System.out.println(annotation + " => " + author + ", " + date + ", " + description);
}
}
}
}
参考资料
文档信息
- 本文作者:Bob.Zhu
- 本文链接:https://adolphor.github.io/2016/09/27/annotation-tutorial/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)