深入理解Java:注解(Annotation)基本概念

一、什么是注解(Annotation)

  Annotation是Java提供的一种元程序中的元素用来关联任何信息和任何元数据(metadata)的途径和方法。

  Annotion是一个接口,程序可以通过反射来获取指定程序元素的Annotation(注解)对象,然后通过Annotation对象来获取注解里面的元数据。

  Annotation可以用于创建文档(例如:@Description、@Date、@Created、@author、@see、@since等等),跟踪代码中的依赖性,甚至执行基本编译检查。从某些方面看,annotation就像修饰符一样被使用,并应用于包、类 型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在Annotation的“name=value”结构对中。

  Annotation类型的成员(指注解中的字段)在Annotation类型使用类似一个无参数方法的格式来声明。其方法名(=>字段名)和返回值(=>类型)定义了该成员的名字和类型。在此有一个特定的默认语法:允许声明任何Annotation成员的默认值:一个Annotation类型可以将name=value对作为没有定义默认值的Annotation成员的值,当然也可以使用name=value对来覆盖其它成员默认值。这一点有些近似类的继承特性,父类的构造函数可以作为子类的默认构造函数,但是也可以被子类覆盖。

  Annotation能被用来为某个程序元素(ElementType中枚举的值都称为程序元素)关联任何的信息。需要注意一个基本原则:Annotation不能影响程序代码的执行,无论增加、删除 Annotation,代码都始终如一的执行。另外,尽管一些annotation通过java的反射api方法在运行时被访问,而JVM在工作时会忽略annotation。由于JVM虚拟机忽略了Annotation,导致annotation类型在代码中看似是“不起作用”的; 只有通过某种配套的工具才会对annotation类型中的信息进行访问和处理来影响程序的行为。本文中将涵盖标准的Annotation和meta-annotation类型,陪伴这些annotation类型的工具是java编译器。

二、什么是metadata(元数据)

  metadata(元数据)既描述数据的数据;(例如:数据库中字段的约束条件就是元数据)
  元数据的功能作用有很多,比如:用Javadoc的注释自动生成文档。就是元数据功能的一种。总的来说,元数据可以用来创建文档,跟踪代码的依赖性,执行编译时格式检查,代替已有的配置文件。

如果要对元数据的作用进行分类,目前还没有明确的定义,不过根据所起的作用,大致可分为三类:

  1. 编写文档:通过代码里标识的元数据生成文档
  2. 代码分析:通过代码里标识的元数据对代码进行分析
  3. 编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查

  在Java程序中元数据以标签的形式存在于Java代码中,元数据标签的存在并不影响程序代码的编译和执行,它只是被用来生成其它的文件或针在运行时知道被运行代码的描述信息。

综上所述:

  • 元数据以标签的形式存在于Java代码中。
  • 元数据描述的信息是类型安全的,即元数据内部的字段都是有明确类型的。
  • 元数据需要编译器之外的工具额外的处理用来生成其它的程序部件。
  • 元数据可以只存在于Java源代码级别,也可以存在于编译之后的Class文件内部。

三、 Annotation和Annotation类型

  • Annotation

  Annotation使用了java5.0后的新语法,它的行为十分类似public、final这样的修饰符。每个Annotation具有一个名字和成员个数>=0。每个Annotation的成员具有被称为name=value对的名字和值,name=value装载了Annotation的信息。

  • Annotation类型

  Annotation类型定义了Annotation的类型、名称、成员默认值。一个Annotation类型可以说是一个特殊的java接口,它的成员变量是受限制的,声明Annotation类型时需要使用新语法。当通过java反射api访问Annotation时,返回值将是一个实现了该 annotation类型接口的对象,通过访问这个对象我们能方便的访问到其Annotation成员。

四、注解的分类

1、根据Annotation类型成员的个数可分为三类:

  • 标记注解
    • 一个没有成员定义的Annotation类型被称为标记注解。这种Annotation类型仅使用自身的存在与否来提供信息。比如系统注解@Override等
  • 单值注解
  • 完整注解  

2、根据注解使用方法和用途,可以分为三类:

  • DK内置系统注解
  • 元注解
  • 自定义注解

五、系统内置标准注解

JavaSE中内置三个标准注解,定义在java.lang包中:

  • @Override:被此注解修饰的方法必须重写了父类中的方法;
  • @Deprecated:用来修饰已经过时的方法;
  • @SuppressWarnnings:用于镇压特定的编译警告。

三个内置标准注解的作用和使用场景

  1. @Override

  是一个标记注解类型,对程序的方法元素进行标记。被标记的方法必须要重写父类的同名方法,有断言的作用。如果使用了这种Annotation在一个没有覆盖父类方法的方法时,java编译器将以一个编译错误来警示。这个annotaton常常在我们试图覆盖父类方法而确又写错了方法名时发挥威力。

  1. @Deprecated

  也是一个标记注解。当一个程序元素使用@Deprecated修饰时,编译器将不建议使用这个被标注的程序元素。该注解有一定“继承性”,如果在代码中通过继承或者覆盖的方式使用了这个过时的程序元素,虽然继承或者覆盖后的程序元素并未被 @Deprecated标记,也会出现编译警告。

  @Deprecated这个annotation类型和javadoc中的 @deprecated标签是有区别的:前者被java编译器识别,后者被javadoc工具识别用来生成文档。

  1. @SuppressWarnings

  被用于有选择的关闭编译器对特定程序元素的警告。例如当使用一个generic collection类而没有提供泛型类型时,编译器将提示出"unchecked warning"的警告。在例如警告信息表明代码中的switch语句没有覆盖所有可能的case,就应增加一个默认的case来避免这种警告。
  在无法避免警告时,例如,在与必须和没有泛型的旧代码交互过程中使用generic collection类时,不可避免unchecked warning。此时@SuppressWarnings就派上用场,增加@SuppressWarnings修饰,编译器将停止对此程序元素警告。
  @SuppressWarnings不是标记注解。它有一个类型为String[]的成员,这个成员的值为被镇压警告类型的警告名。
  annotation语法允许在annotation名后跟括号,括号中是使用逗号分割的name=value对用于为annotation的成员赋值。例如:@SuppressWarnings({"rawtypes","unchecked"})

  @SuppressWarnings注解常见参数值:

    1.deprecation:镇压过时警告;
    2.unchecked:镇压类型未检查警告,例如集合未指定泛型时;
    3.fallthrough:镇压Switch程序块直接通往下一种情况并且没有 Break时的警告;
    4.path:镇压不存在的路径警告;
    5.serial:镇压可序列化类上缺少 serialVersionUID 定义时的警告;
    6.finally:镇压任何 finally 子句不能正常完成时的警告;
    7.all:镇压关于以上所有情况的警告。

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利
原文地址:https://www.cnblogs.com/hhddd-1024/p/15322422.html