Java 注解(Annotation)
一 什么是注解?
Annontation是Java5开始引入的新特征,中文翻译为注解,注解可以理解为描述数据自身的数据。即注解就是代码的元数据,他们包含了代码自身的信息。注解可以作用在包,类,方法,变量以及参数上。
二 注解基本使用
2.1 注解的声明
可以通过以下方式声明一个注解:
//声明一个Test注解
@Target(ElementType. TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation{
}
这样,就声明了一个TestAnnotation注解,然后该注解怎么使用呢?
2.2 注解的使用
上面创建了一个注解,那么注解的的使用方法是什么呢。
@TestAnnotation
public class TestClass {
}
创建一个类 TestClass,然后在类定义的地方加上 @TestAnnotation 就可以用 TestAnnotation 注解这个类了。
虽然通过上述声明,就可以使用,但要想理解注解的更详细的工作,还需要介绍一下元注解。
2.3 元注解
元注解是可以注解到注解上的注解,或者说元注解是一种基本注解,但是它能够应用到其它的注解上面,元标签有: @Target、@Retention、@Documented、@Inherited、@Repeatable 5 种,下面分别介绍。
2.3.1 @Target
@Target是用来约束注解可以应用的地方(如方法、类或字段等),其中ElementType是枚举类型,可以的取值有:
ElementType 值 | 含义 |
---|---|
ElementType. TYPE | 用于类、接口(包括注解类型)、枚举 |
ElementType. FIELD | 用于字段(域)声明 |
ElementType. METHOD | 用于方法声明 |
ElementType. PARAMETER | 用于参数声明 |
ElementType. CONSTRUCTOR | 用于构造函数声明 |
ElementType. LOCAL_VARIABLE | 用于局部变量声明 |
ElementType.ANNOTATION_TYPE | 用于注解声明(即应用于另一个注解上) |
ElementType. PACKAGE | 用于包声明 |
ElementType. TYPE_PARAMETER | 用于类型参数声明(1.8新加入) |
ElementType. TYPE_USE | 类型使用声明(1.8新加入) |
2.3.2 @Retention
@Retention用来约束注解的生命周期,分别有三个值,源码级别(source),类文件级别(class)或者运行时级别(runtime),其含有如下:
RetentionPolicy 值 | 含义 |
---|---|
RetentionPolicy.SOURCE | 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视 |
RetentionPolicy.CLASS | 注解在class文件中可用,它并不会被加载到 JVM 中 |
RetentionPolicy.RUNTIME | 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中。 |
2.3.3 @Documented
@Documented作用是能够将注解中的元素包含到 Javadoc 中去
2.3.4 @Inherited
@Inherited可以让注解被继承,但这并不是真的继承,只是通过使用@Inherited,可以让子类Class对象使用getAnnotations()获取父类被@Inherited修饰的注解
2.3.5 @ Repeatable
@Repeatable 是 Java 1.8 才加进来的,它表示在同一个位置重复相同的注解。
三 Java内置的注解
Java提供的内置注解,常见的主要有3个,如下:
3.1 @Deprecated
用于标明已经过时的方法或类,这个在编码时经常会碰到的,主要是告诉开发者正在调用一个过时的元素比如过时的方法、过时的类、过时的成员变量。源码如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
3.2 @Override
@Override用于标明此方法覆盖了父类的方法,也是大家很熟悉了的一个注解,源码如下:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
3.3 @ SuppressWarnnings
@ SuppressWarnnings用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告,也是大家很熟悉了的一个注解,源码如下:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
四 自定义注解实例
声明一个自定义注解:
//类注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestClassAnno {
public int id() default -1;
public String message() default "test";
}
//域注解
@Target(FIELD)
@Retention(RUNTIME)
@Documented
public @interface TestFieldAnno {
String value() default "";
}
编写一个注解处理器类 AnnotationDemo 就可以测试上述的自定义注解。
@TestClassAnno(id=1,message="类注解测试")
public class AnnotationDemo{
@TestFieldAnno(value="域注解测试")
String name;
public static void main(String[] args){
boolean hasAnnotation = AnnotationDemo.class.isAnnotationPresent(TestClassAnno.class);
if ( hasAnnotation ) {
TestClassAnno testAnnotation = AnnotationDemo.class.getAnnotation(TestClassAnno.class);
System.out.println("id:"+testAnnotation.id());
System.out.println("msg:"+testAnnotation.msg());
}
try {
Field name = AnnotationDemo.class.getDeclaredField("name");
name.setAccessible(true);
//获取一个成员变量上的注解
TestFieldAnno testFieldAnno = AnnotationDemo.class.getAnnotation(TestFieldAnno.class);
if ( testFieldAnno != null ) {
System.out.println("testFieldAnno name:"+testFieldAnno.name());
}
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
五注解的知名类库
Java中一些类库:JAXB, Spring Framework, Findbugs, Log4j, Hibernate, JUnit等
Android中的一些类库:ButterKnife、Dagger2、Retrofit等。