Java注解——这些@圈圈都是个啥?

一、啥是@ 注解

  首先看名字,注解——跟注释长得挺像。注解跟注释很类似,类比思考一下,注释是干什么用的?

  /**

  * 注释是一种存在于源代码中的信息,用于开发过程中给程序员提示和帮助。

  **/

  注解也是类似的东西,他也带来信息,不过跟注释不一样的地方在于,注解可以保留到编译之后的二进制代码中,而注释则在编译阶段就被抛弃了。

  由于注解拥有可以保留到二进制代码中的特征,因此可以通过注解为框架带来元信息。

  举个例子:最常用的注解之一@Controller 将这个注解标注到Controller类上,在springMVC(一种java mvc框架)构建ApplicationContext环境的时候,就会发现,哦这是一个控制器,这个控制器要映射到url上。这就相当于在类上面添加了一个能保留到二进制代码中的//这是一个控制器类 这么一段注释。

二、注解的语法

定义注解时,需要一些元注解(meta-annotation),如@Target和@Retention

  • @Target用来定义注解将应用于什么地方(如一个方法或者一个域)

  • @Retention用来定义注解在哪一个级别可用,在源代码中(source),类文件中(class)或者运行时(runtime)

  • 在注解中,一般都会包含一些元素以表示某些值。当分析处理注解时,程序可以利用这些值。没有元素的注解称为标记注解(marker annotation)

  • 四种元注解,元注解专职负责注解其他的注解,所以这四种注解的Target值都是ElementType.ANNOTATION_TYPE

注解说明
@Target 表示该注解可以用在什么地方,由ElementType枚举定义 
CONSTRUCTOR:构造器的声明 
FIELD:域声明(包括enum实例) 
LOCAL_VARIABLE:局部变量声明 
METHOD:方法声明 
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明 
ANNOTATION_TYPE:注解声明(应用于另一个注解上)
TYPE_PARAMETER:类型参数声明(1.8新加入) 
TYPE_USE:类型使用声明(1.8新加入)
PS:当注解未指定Target值时,此注解可以使用任何元素之上,就是上面的类型
@Retention 表示需要在什么级别保存该注解信息,由RetentionPolicy枚举定义 
SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
CLASS:注解在class文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机(JVM)中)
RUNTIME:VM将在运行期也保留注解信息,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息)
PS:当注解未定义Retention值时,默认值是CLASS
@Documented 表示注解会被包含在javaapi文档中
@Inherited 允许子类继承父类的注解

 

注解元素

 

  • 注解元素可用的类型如下:

    • 所有基本类型(int,float,boolean,byte,double,char,long,short)

    • String

    • Class

    • enum

    • Annotation

    • 以上类型的数组 如果使用了其他类型,那编译器就会报错。也不允许使用任何包装类型。注解也可以作为元素的类型,也就是注解可以嵌套。 元素的修饰符,只能用public或default。

  • 默认值限制

    编译器对元素的默认值有些过分挑剔。首先,元素不能有不确定的值。也就是说,元素必须要么具有默认值,要么在使用注解时提供元素的值。

    其次,对于非基本类型的元素,无论是在源代码中声明,还是在注解接口中定义默认值,都不能以null作为值。这就是限制,这就造成处理器很难表现一个元素的存在或缺失状态,因为每个注解的声明中,所有的元素都存在,并且都具有相应的值。为了绕开这个限制,只能定义一些特殊的值,例如空字符串或负数,表示某个元素不存在。

@Target(ElementType.Method)

@Retention(RetentionPolicy.RUNTIME)

public @interface MockNull {

    public int id() default -1;

    public String description() default "";

}

三、注解的使用

说过了注解是什么东西,注解怎么定义,该说说注解如何使用了。

首先声明一点,注解都是给框架用的,说到框架使用,很容易联想到反射。

<A extends Annotation
A
getAnnotation(Class<A> annotationClass) 
          如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
 Annotation[] getAnnotations() 
          返回此元素上存在的所有注释。

 Filed类等可以拥有注解的反射类型都有类似可以获取注解的方法

<T extends Annotation
T
getAnnotation(Class<T> annotationClass) 
          如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。

四、总结

注解在java中属于一种比较高级而且麻烦的技术,非框架编写者基本不会用到这种技术。但是了解注解是个什么东西很重要,因为注解在框架的快捷配置中起了决定性的作用,也让no xml党们拥有了一个脱离xml配置的机会。了解注解可以让我们不止知其然还知其所以然,在使用框架的时候不至于迷迷糊糊的就@了个圈在上面。

原文地址:https://www.cnblogs.com/wencheng256/p/5661644.html