注解----1
注解的基本概念及分类 内建注解
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
1. 注解的基本概念以分类
1). 注解的基本概念
(1). 注解的前景 (发展前景非常好)
未来的开发模式的一种趋势就是基于注解的开发模式
(2). 注解
[1]. 注解就是Java代码中的特殊标记
【另一种看法】注解可以看成是在不改变原有逻辑的情况下,向源文件中加入的补充信息
[2]. 程序元素:包括类名、方法名、属性、方法参数及局部变量等。
(3). 注解的作用
[1]. 用于向编译器javac,代码开发工具 (如eclipse)、分析工具或者部署工具或者其他程序一种普通Java语句无法表达的信息。
-----以上工具可以通过注解 (源文件的补充信息)进行一些验证和操作
e.g1. javac编译器看到了@Deprecated,就会在eclipse的界面中@Deprecated修饰的元素上打删除线,用于提示开发人员这种方法不再被推荐使用。但是这并不影响源代码的编译和执行。真正执行的时候,程序该怎么做还是怎么做。
e.g2. javac编译器看到了@SurppressWarnings,就会在eclipse标记处警告的地方取出黄色警告。但是,这仅仅提示开发人员这样做可能压制了潜在的问题,不会影响程序的编译和执行。
【javac看到注解 (一种标记),就会去作相应的动作】
[2]. 注解可以修饰Java程序中的任何程序元素。
【注意】注解的存在不影响程序的编译和执行。无论增加
注解只是用来生成其他文件或者使开发人员获取代码被运行时的描述信息。
2). 注解的分类
注解按照使用的方式和用途,注解可以分成以下三种:
(1).内建注解
[1]. 内建注解也成为基本注解
[2]. 位置:内建注解位于java.lang包下
[3]. 内建注解有三个:
{1}. 限定重写父类方法: @Override
{2}. 标示方法已经过时: @Deprecated
{3}. 抑制编译器警告: @SuppressWarnings
(2). 元注解
[1]. 位置:元注解位于java.lang.annotation子包下
[2]. 作用:用于修饰其他注解
[3]. 元注解有四个:( Meta Annotation )
@Retention,@Target,@Documented,@Inherited
(3). 自定义注解
需要用到关键字@interface来定义
3). 注解的生命周期
注解的生命周期有3种,注解驻留在源文件阶段,字节码文件阶段和内存字节码阶段
(1). 注解被保留到源文件解阶段
此时javac将.java源文件编译成.class时,就将相应的注解去掉。这种注解的生命周期就维持到源文件阶段。
(2). 注解被保留到字节码文件阶段
在JVM通过ClassLoader向内存中加载字节码文件时候,JVM会去掉相应的注解。这种注解的生命周期就维持到字节码文件阶段。
【注意】生命周期到源文件阶段和字节码文件阶段的注解,由于JVM执行内存中的字节码时候,相应的注解已经被Javac或者JVM去除,所以无法使用反射来访问相应的注解。
(3). 注解被保留到内存字节码阶段
JVM运行内存的字节码时候,仍然可能会保留并且执行的某些注解。这种注解的生命周期就维持到内存字节码阶段。
【注意】程序可以通过反射访问生命周期到内存字节码阶段的注解。
2. 元注解
元注解位于java.lang.annotation子包下面。用于修饰注解的注解
元注解描述了被元注解修饰的注解的作用范围、生命周期、是否被javadoc识别、
1). @Target
(1). 源码
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
【注意】@Target类型定义中,仅含有一个ElementType数组类型的变量value
(2). 作用
用于指定被修饰的注解的适用范围,即被修饰的注解可以用来修饰哪些程序元素
(3). @Target中value属性的取值:ElementType[]类型
[1]. ElementType枚举类源码
package java.lang.annotation;
public enum ElementType {
TYPE, FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE
}
[2].ElementType是一种枚举类型,枚举成员含义如下
【含义】不同的枚举成员表示被修饰的注解具有不同的生命周期
{1}. TYPE:类类型、接口类型 (注解类型)、枚举类型声明
{2}. FIELD:成员属性声明 (包括枚举常量成员)
{3}. METHOD:成员方法声明
{4}. PARAMETER:参数声明
{5}.CONSTRUCTOR:构造方法声明
{6}. LOCAL_VARIABLE:局部变量声明
{7}. ANNOTATION_TYPE:注解类型声明
【注意】这种类型和TYPE的区别
{7}1. TYPE:可以表示多种数据类型,这些被TYPE表示的数据类型的中包含了ANNOTATION_TYPE这种类型。
{7}2. ANNOTATION_TYPE仅仅就表示注解类型一种。
{8}. PACKAEG:包声明
2). @Retention
(1). 源码
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
(2). 作用
用来描述被修饰的注解的生命周期
(3). @Retention中value属性的取值:RetentionPolicy类型
[1]. ElementType枚举类源码
package java.lang.annotation;
public enum RetentionPolicy {
SOURCE, CLASS, RUNTIME
}
[2]. RetentionPolicy是一种枚举类型
【含义】不同的枚举成员表示被修饰的注解具有不同的生命周期
{1}. SOURCE:表示被修饰的注解的生命周期持续到源文件阶段
被取值是SOURCE的@Retention修饰的注解被Javac编译完成之后就丢弃
{2}. CLASS:成员属性声明 (包括枚举常量成员)
被取值是CLASS的@Retention修饰的注解被Javac编译完成之后会保留在字节码文件中。但是在字节码被JVM运行时,不被JVM所保留
【注意】@Retention的value的默认取值就是RetentionPolicy.CLASS
{3}. RUNTIME:成员方法声明
3). @Documented
(1). 源码
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
(2). 作用
[1]. 用于指定被修饰的注解将被javadoc工具提取成文档。
[2]. 如果定义注解的时候使用了@Documented进行了修饰,则使用了@Documented注解修饰的注解所修饰的其他程序元素的API文档都会包含该注解的说明。
4). @Inherited
(1). 源码
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
(2). 作用
[1]. 用于指定被@Inherited修饰的注解具有继承性
[2]. 如果某个类使用了@Inherited修饰的注解,那么这个类的子类将自动继承这个被@Inherited修饰的注解。
5). 四种元注解的相似性
(1). 四种元注解都被@Documented、@Retention和@Target来修饰
[1]. 对于@Documented、@Retention和@Target这三种注解是相互修饰并且还修饰自身的。
[2]. @Inherited也被其他三种元注解来修饰,但是他没有修饰其他元注解,也没有修饰自身。
(2). 四种元注解的特性
| @Documented修饰 | @Retention修饰 | @Target修饰 | 属性名 | 属性数据类型 |
@Documented |
————————— |
RUNTIME
|
ANNOTATION_TYPE | —— | —— |
@Retention | value | RetentionPolicy | |||
@Target | ElementType[] 数组 | ||||
@Inherited | —— | —— |
[1]. 四种元注解本身的生命周期都是一直到内存字节码阶段的。
如果直接使用这四种元注解修饰其他注解(如果被修饰的注解本身的生命周期也能延续到内存字节码的情况下) 的时候,一定可以通过反射来访问这四种元注解对应的ANNOTATION对象。
[2]. 四种元注解本身的修饰范围只能是其他注解,而不能修饰非注解种类的程序元素。
元注解的定义就是修饰注解的注解,所以正好符合元注解的基本定义。
[3]. 四种元注解本身都能被javadoc工具识别并提取成文档。
[4]. 四种元注解本身最多有一个属性变量,如果有的话,变量的名就是value。
{1}. 但是变量的数据类型不一定。
@Target属性value的数据类型是ElementType数组类型【枚举数组】
@Retention属性value的数据类型是RetentionPolicy类型【枚举】
{2}. 如果注解的属性变量只有一个并且属性名是value的时候,使用这些注解修饰其他元素的时候,就不用写变量名,直接给出变量的取值即可。
{3}. @Documented和@Inherited注解没有属性变量
e.g.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
【分析】本来应该写成@Retention(value =RetentionPolicy.RUNTIME)和@Target(value = ElementType.ANNOTATION_TYPE)。但是,由于@Retention和@Target的成员变量只有一个value,所以使用的时候,可以简化到不写变量名
【注意】这条规律适用于所有类型的注解,不一定局限在元注解范围内。内建注解和自定义注解也遵循这样的规律。
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------