Java注解总结(史上最全,有这一篇就够了)

什么是注解?

注解的定义

官网描述以下:java

Java 注解用于为 Java 代码提供元数据。做为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上能够用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。spring

将上面的话再翻译一下,以下:
(1)元数据在开发中的做用就是作数据约束和标准定义,能够将其理解成代码的规范标准(代码的模板);
(2)代码的模板(元数据)不直接影响代码的执行,它只是帮助咱们来更快捷的开发;服务器

综上,注解是一种元数据,能够将它理解为注释、解释,它为咱们在代码中添加信息提供了一种形式化的方法,它用于帮助咱们更快捷的写代码。markdown

注解的分类

通常经常使用的注解能够分为三类: 架构

一、Java自带的标准注解
包括@Override、@Deprecated、@SuppressWarnings等,使用这些注解后编译器就会进行检查。ide

二、元注解
元注解是用于定义注解的注解,包括@Retention、@Target、@Inherited、@Documented、@Repeatable 等。
元注解也是Java自带的标准注解,只不过用于修饰注解,比较特殊。函数

三、自定义注解
用户能够根据本身的需求定义注解。源码分析

注解的使用

使用Java自带的注解
Java 自带的注解,就是 java.lang中定义的一套注解,以Override注解为例,使用方法以下:翻译

@Override         //在须要注解的方法上面@Override便可
protected void onCreate() {

}

经常使用的Java注解以下:code

一、@Deprecated – 所标注内容再也不被建议使用;
二、@Override – 只能标注方法,表示该方法覆盖父类中的方法;
三、@Documented --所标注内容能够出如今javadoc中;
四、@Inherited – 只能被用来标注“Annotation类型”,它所标注的Annotation具备继承性;
五、@Retention – 只能被用来标注“Annotation类型”,并且它被用来指定Annotation的RetentionPolicy属性;
六、@Target – 只能被用来标注“Annotation类型”,并且它被用来指定Annotation的ElementType属性;
七、@SuppressWarnings – 所标注内容产生的警告,编译器会对这些警告保持静默;
八、@interface – 用于定义一个注解;

其中,四、五、六、8多用于自定义注解,读者着重记一下。

自定义注解

在Java中,咱们使用@interface注解来自定义一个注解,以下:

public @interface MyTestAnnotation {

}

此时,咱们已经定义了一个注解MyTestAnnotation ,接着咱们就能够在类或者方法上做用咱们刚刚新建的注解:

@MyTestAnnotation
public class Test {
   @MyTestAnnotation
   public static void testString(){
   }
}

此时,咱们已经自定义了一个注解,不过如今这个注解毫无心义。

要如何使注解工做呢?这就须要使用元注解了。

经常使用的元注解有@Retention、 @Target、 @Document、 @Inherited和@Repeatable五个。

@Retention
Retention英文意思有保留、保持的意思,它表示注解存在阶段是保留在源码(编译期),字节码(类加载)或者运行期(JVM中运行)。

在@Retention注解中使用枚举RetentionPolicy来表示注解保留时期:

  • @Retention(RetentionPolicy.SOURCE),注解仅存在于源码中,在class字节码文件中不包含
  • @Retention(RetentionPolicy.CLASS), 默认的保留策略,注解会在class字节码文件中存在,但运行时没法得到
  • @Retention(RetentionPolicy.RUNTIME), 注解会在class字节码文件中存在,在运行时能够经过反射获取到

若是咱们是自定义注解,则经过前面分析,咱们自定义注解若是只存着源码中或者字节码文件中就没法发挥做用,而在运行期间能获取到注解才能实现咱们目的,因此自定义注解中确定是使用 @Retention(RetentionPolicy.RUNTIME),以下:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyTestAnnotation {

}

@Target
Target的英文意思是目标,这也很容易理解,使用@Target元注解表示咱们的注解做用的范围就比较具体了,能够是类,方法,方法参数变量等,一样也是经过枚举类ElementType表达做用类型:

  • @Target(ElementType.TYPE) 做用接口、类、枚举、注解
  • @Target(ElementType.FIELD) 做用属性字段、枚举的常量
  • @Target(ElementType.METHOD) 做用方法
  • @Target(ElementType.PARAMETER) 做用方法参数
  • @Target(ElementType.CONSTRUCTOR) 做用构造函数
  • @Target(ElementType.LOCAL_VARIABLE)做用局部变量
  • @Target(ElementType.ANNOTATION_TYPE)做用于注解(@Retention注解中就使用该属性)
  • @Target(ElementType.PACKAGE) 做用于包
  • @Target(ElementType.TYPE_PARAMETER) 做用于类型泛型,即泛型方法、泛型类、泛型接口 (jdk1.8加入)
  • @Target(ElementType.TYPE_USE) 类型使用.能够用于标注任意类型除了 class (jdk1.8加入)

通常比较经常使用的是ElementType.TYPE类型,以下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyTestAnnotation {

}

@Documented
Document的英文意思是文档。它的做用是可以将注解中的元素包含到 Javadoc 中去。

@Inherited
Inherited的英文意思是继承,可是这个继承和咱们平时理解的继承大同小异,一个被@Inherited注解了的注解修饰了一个父类,若是他的子类没有被其余注解修饰,则它的子类也继承了父类的注解。

@Repeatable
Repeatable的英文意思是可重复的。顾名思义说明被这个元注解修饰的注解能够同时做用一个对象屡次,可是每次做用注解又能够表明不一样的含义。

注解的源码分析
咱们以@Override注解为例,来分析其源码,想查看一个普通类同样,按住ctrl键点击@Override便可进入其源码,以下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

咱们看到@Override注解就是经过@interface注解定义的一个普通注解,而咱们知道,使用 @interface 定义注解时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注解就是一个Annotation

注意:定义 Annotation 时,@interface 是必须的,它和咱们一般的 implemented 实现接口的方法不一样。Annotation 接口的实现细节都由编译器完成。经过 @interface 定义注解后,该注解不能继承其余的注解或接口。

下面咱们来分析一下Annotation 类的源码,以下:

public interface Annotation {
    boolean equals(Object var1);

    int hashCode();

    String toString();

    Class<? extends Annotation> annotationType();
}

经过以上源码,咱们知道注解自己就是Annotation接口的子接口,也就是说注解中实际上是能够有属性和方法,可是接口中的属性都是static final的,对于注解来讲没什么意义,而咱们定义接口的方法就至关于注解的属性,也就对应了前面说的为何注解只有属性成员变量,其实他就是接口的方法,这就是为何成员变量会有括号,不一样于接口咱们能够在注解的括号中给成员变量赋值。

Java注解的架构

根据上述的源码分析,咱们得出Java注解(Annotation)的架构以下:

Java注解总结(史上最全,有这一篇就够了)

0、注解是接口类,都继承自Annotation接口类

一、1 个 Annotation 和 1 个 RetentionPolicy 关联
能够理解为:每1个Annotation对象,都会有惟一的RetentionPolicy属性;

二、1 个 Annotation 和 1~n 个 ElementType 关联
能够理解为:对于每 1 个 Annotation 对象,能够有若干个 ElementType 属性;

三、Annotation 有许多实现类,包括:Deprecated, Documented, Inherited, Override 等等。
Annotation 的每个实现类都和1个 RetentionPolicy 关联而且和 1~n 个 ElementType 关联。

注解的做用

在说注解的用途以前,咱们先介绍下XML和注解区别:

  • 注解:是一种分散式的元数据,与源代码紧绑定。
    xml:是一种集中式的元数据,与源代码无绑定
    这部分多用于Java后台的配置项开发中,咱们知道几年前服务器的配置项多存放在一个xml文件中,而spring 2.5 以后开始基于注解配置,从而实现了代替配置文件的功能。

注解的用途有不少,上面的只是一个简单的例子,总起起来,注解有以下四大部分做用:

一、生成文档,经过代码里标识的元数据生成javadoc文档。

二、编译检查,经过代码里标识的元数据让编译器在编译期间进行检查验证。

三、编译时动态处理,编译时经过代码里标识的元数据动态处理,例如动态生成代码。

四、运行时动态处理,运行时经过代码里标识的元数据动态处理,例如使用反射注入实例

相关文章
相关标签/搜索