【java】细说 JAVA中 标注 注解(annotation)

Java 注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用

下面我们来详细说说这个注解,到底是怎么一回事,一步一步看下去,总会后收获。

注解起源:Annotation(注解) 是 JDK5.0 及以后版本引入的。在java.lang.annotation包中。

注解作用:它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。

注解格式:注解是以‘@注解名’在代码中存在的

注解分类:标记注解、单值注解、完整注解三类

另外:它都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射机制编程实现对这些元数据的访问。

元注解说,我先来上阵 -----

------------------------------main-----------------------------------

一、元注解:

元注解功能:就是对其他注解进行注解。

我们它的功能划分为三类:

  编写文档:通过代码里标识的元数据生成文档;

  代码分析:通过代码里标识的元数据对代码进行分析;

  编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查。

元注解包括:@Retention @Target @Document @Inherited 四种。


@Target 注解:

---------------------------------------------------

@Target 解释:

  @Target 说明了 Annotation 所修饰的对象范围:

    Annotation 可被用于 packages、types(类、接口、枚举、Annotation 类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循 环变量、catch 参数)。

    在 Annotation 类型的声明中使用了 target 可更加明晰其修饰的目标。

@Target 作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

@Target 的 java 源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {ElementType[] value();}

 

  备注:先解释一下 interface 表示接口,而 @interface 表示 annotation

——————————————————————————

ElementType 取值:

    通过源码可以看到,ElementType ,它的取值有:

    1.CONSTRUCTOR: 用于描述构造器
    2.FIELD: 用于描述域
    3.LOCAL_VARIABLE: 用于描述局部变量
    4.METHOD: 用于描述方法
    5.PACKAGE: 用于描述包
    6.PARAMETER: 用于描述参数
    7.TYPE: 用于描述类、接口 (包括注解类型) 或 enum 声明

------------------------------------------------

实例: (我们自定义了两个自定义注解,按照上面我们给出的取值含义,@table 将会用于类、接口或 enum 声明)

@Target(ElementType.TYPE)
public @interface Table {
    /**
     * 数据表名称注解,默认值为类名称
     * @return
     */
    public String tableName() default "className";
}

@Target(ElementType.FIELD)
public @interface NoDBColumn {

}

 那么到这里,我们的 @Target 元注解解释完毕,有不明白地方, @企鹅:2783309477

 


 @Retention 注解:

 

@Retention 精简解释:

  就是对自定义注解的生命周期的管理

@Retention 详细解释:

  @Retention 定义了该 Annotation 被保留的时间长短:某些 Annotation 仅出现在源代码中,而 被编译器丢弃;而另一些却被编译在 class 文件中;编译在 class 文件中的 Annotation 可能会被虚拟机忽略,而另一些在 class 被装载时将 被读取(请注意并不影响 class 的执行,因为 Annotation 与 class 在使用上是被分离的)。使用这个 meta-Annotation 可以对 Annotation 的“生命周期”限制

 ——————————————————————————————

@Retention: 定义注解的保留策略

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

 ——————————————————————————————

@Retention java 源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {RetentionPolicy value();
}

 

  通过源代码可以看到 RetentionPolicy 可取值。那么接下来

———————————————————————————————

@Retention  取值:

  RetentionPolicy 可取值:

    1.SOURCE: 在源文件中有效(即源文件保留)
    2.CLASS: 在 class 文件中有效(即 class 保留)
    3.RUNTIME: 在运行时有效(即运行时保留)

@Retention 实例:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    public String name() default "fieldName";
    public String setFuncName() default "setField";
    public String getFuncName() default "getField"; 
    public boolean defaultDBValue() default false;
}

 

备注:也同样,可以看出来,Column 将会有在运行时有效范围。

  一般格式:

  @Retention(RetentionPolicy.SOURCE)   // 注解仅存在于源码中,在 class 字节码文件中不包含

  @Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在 class 字节码文件中存在,但运行时无法获得,

  @Retention(RetentionPolicy.RUNTIME)  // 注解会在 class 字节码文件中存在,在运行时可以通过反射获取到

  OK,这个就解释到这里,有不明白 @小企鹅:2783309477(如是),接下来


 @Documented 元注解:

  @Documented 用于描述其它类型的 annotation 应该被作为被标注的程序成员的公共 API,

  因此可以被例如 javadoc 此类的工具文档化。

  Documented 是一个标记注解,没有成员。

@Document java 源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

 

@Document 实例:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
    public String name() default "fieldName";
    public String setFuncName() default "setField";
    public String getFuncName() default "getField"; 
    public boolean defaultDBValue() default false;
}

 

 


 @Inherited 元注解:
  
@Inherited 解释:
  是一个标记注解,@Inherited 阐述了某个被标注的类型是被继承的。
  也就是说,如果被它修饰的 annotation 类型用在一个类上面, 这个 annotation 将被用在子类中。
  注意:
    1、@Inherited annotation 类型是被标注过的 class 的子类所继承。
      类并不从它所实现的接口继承 annotation,方法并不从它所重载的方法继承 annotation。
    2、当 @Inherited annotation 类型标注的 annotation 的 Retention 是 RetentionPolicy.RUNTIME,
      则反射 API 增强了这种继 承性。如果我们使用 java.lang.reflect 去查询一个 @Inherited annotation
      类型的 annotation 时,反射代码检查将展开工作:检查 class 和其父类,直到发现指定的 annotation 类型
      被发现, 或者到达类继承结构的顶层。

 
 未完待续(自定义注解 / 默认注解 /...)