什么是注解?
注解是Java5.0之后引入的新特性,注解可以理解为一种描述数据的数据.比如我们非常熟悉的@Override就是一个注解.
@Override注解是用于修饰在类中的方法上的(如果你用这个注解去修饰类或者类的成员变量是会报错的),表示该方法是重写了父类的方法.
还有一个奇怪的现象,当你去反编译一个使用了@Override注解的类时,你会发现反编译出来的时候,这个注解消失了.但是如果你的类中也使用了@Deprecated(表示已经不推荐使用了)注解时,你会发现反编译之后该注解没有消失.并且你会发现@Deprecated可以修饰类!
通过这几个简单的情况,我们可以了解到,不同的注解可以修饰的东西不同,并且不同的注解被保留的时间段不同.其实注解还有其他的特性,下面将逐步介绍.
元注解
先抛开上面的问题不谈,我们来看看@Override和@Deprecated到底是什么.我们在java.lang包下可以找到这两个注解的定义:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
和
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
我们会发现原来这些个注解也是事先在JDK中定义好的,那我们可不可以自己定义注解然后使用呢?当然是可以的,这我们就需要了解元注解了,你可以将其理解为定义注解的注解.
Java中定义的元注解有四个,分别为:
- @Target
- @Retention
- @Documented
- @Inherited
我们先来依次介绍一下这四个元注解.
@Target
@Target注解的作用十分简单,就是说明了Annotation所修饰的范围,有如下几种选择:
- ElementType.TYPE:用于描述类、接口(包括注解类型)或enum声明
- ElementType.FIELD:用于描述实例变量
- ElementType.METHOD:用于描述方法
- ElementType.PARAMETER:用于描述方法参数
- ElementType.CONSTRUCTOR:用于描述构造器
- ElementType.LOCAL_VARIABLE:用于描述局部变量
- ElementType.ANNOTATION_TYPE:用于修饰另一个注释
- ElementType.PACKAGE:用于描述包
- ElementType.TYPE_PARAMETER:表示该注解能写在类型参数的声明语句中(JDK8开始提供)
- ElementType.TYPE_USE:表示注解可以在任何用到类型的地方使用(JDK8开始提供)
看到这里,解开了我们一个疑惑,就是@Override只能用于描述方法,我们回想一下刚刚看到的@Override的定义,使用了@Target(ElementType.METHOD)
,所以@Override只能用于描述方法.
@Retention
@Retention注解的作用就是定义了注解的生命周期,有如下几种选择:
1. RetentionPolicy.SOURCE:只在源代码中有效果,编译之后将被丢弃
2. RetentionPolicy.CLASS:编译之后也将保留,但是在类加载的时候被丢弃
3. RetentionPolicy.RUNTIME:一直保留,在运行期也存在
看到这里,又解开了我们另一个疑惑,就是@Override在编译之后不见了,我们回想一下@Override的定义@Retention(RetentionPolicy.SOURCE)
,只在源码中保留.
@Documented
@Documented就很简单了,它只是一个标记注解,表示是否将注解信息添加到java的文档中(javadoc).
@Inherited
@Inherited也是一个标记注解,表示子类是否可以继承该注解.
自定义注解
在了解了元注解的概念之后,我们就可以自定义注解了,定义注解使用了@interface关键字,然后根据你的需要使用特定的元注解即可.