好久没有写点什么了~。。。 计划记录一下java的注解和反射以及这两个好基友的不可描述,这篇先记录一下注解(Annotation)
java基础之反射(Reflect)
注解的基本概念
定义:注解(Annotation),一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。
需要注意的是,这里存在着一个基本的规则:Annotation不能影响程序代码的执行,无论增加、删除 Annotation,代码都始终如一的执行。只有通过某种配套的工具才会对annotation类型中的信息进行访问和处理。从而间接影响程序的走向。
注解一般被用来:
- 编写文档:通过代码里标识的注解生成文档
- 代码分析:通过代码里标识的注解对代码进行分析
- 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查
而我们在日常开发中常用的是上面的第二点,自定定义注解并且对注解进行解析。解析的过程一般是发生在运行时。
内置注解
javaSE中内置的三个注解如下,都是熟面孔
@Override:它的作用是对覆盖超类中方法的方法进行标记,如果被标记的方法并没有实际覆盖超类中的方法,则编译器会发出错误警告。
@Deprecated:用于修饰已经过时的方法;
@SuppressWarnings:用于通知java编译器禁止特定的编译警告。
其中SuppressWarnings在使用的时候需要设置参数值,比如:
@SuppressWarnings(value={ "rawtypes", "unchecked" })
由于SuppressWarnings annotation类型只定义了一个单一的成员,所以只有一个简单的value={...}作为name=value对。又由于成员值是一个数组,故使用大括号来声明数组值。如下:
@SuppressWarnings({ "rawtypes", "unchecked" })
SuppressWarnings注解的常见参数值的简单说明:
- deprecation:使用了不赞成使用的类或方法时的警告;
- unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型;
- fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
- path:在类路径、源文件路径等中有不存在的路径时的警告;
- serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告;
- finally:任何 finally 子句不能正常完成时的警告;
- all:关于以上所有情况的警告。
自定义注解
给注解准备的注解——元注解
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。
- @Documented —— 指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。
- @Target——指明该类型的注解可以注解的程序元素的范围。如果Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。
- CONSTRUCTOR:用于描述构造器
- FIELD:用于描述域
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口(包括注解类型) 或enum声明
- @Inherited——指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。
- @Retention——指明了该Annotation被保留的时间长短。
- SOURCE:在源文件中有效(即源文件保留)
- CLASS:在class文件中有效(即class保留)
- RUNTIME:在运行时有效(即运行时保留)
创建自定义注解
定义注解格式:
public @interface 注解名 {定义体}
- 创建自定义注解和创建一个接口相似,但是注解的interface关键字需要以@符号开头。
- 在定义注解时,不能继承其他的注解或接口。
- 声明一个注解时,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
- 注解里面的参数只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型
- 如果自定义注解时只有一个参数成员,最好把参数名称设为"value",后加小括号例如:String value() default ""; 这样在使用注解的时候可以不显式的指定参数名称。例如:@AnnotationName("valueString")
下面给一个自定义注解的栗子:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation{
/**
* 枚举 状态
*/
public enum Status{ SUCCESS,FAILED,NONE};
/**
* 颜色属性
*/
Status testStatus() default Status.NONE;
String testString() default 'shli';
String testDate();
int testInt() default 1;
}
学会了如何自定义注解,但如果要发挥注解的作用,则在需要的地方添加自定义注解,并且在适当的地方对注解进行处理。
下一篇在记录java反射机制的时候,将介绍对注解的处理。