自定义注解
来源:互联网 发布:c语言标准库是什么 编辑:程序博客网 时间:2024/04/30 02:21
自定义一个注解:
@Inherited@Documented@Target({ElementType.CONSTRUCTOR,ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {long id();String name();boolean gender() default true;String[] hobbies();}
在interface前加一个@符号,表明这是一个注解类型,在这里注解名字为MyAnnotation。在MyAnnotation注解的定义里包括四个属性,分别是id,name,gender和hobbies。乍一看,这四个属性的声明和接口的方法签名类似,有返回类型和方法名,不过还是存在一些差别。首先是注解对返回的数据类型有规定,只能限定为原始类型,String,Class,Annotation,Enum和类型为以上的一维数组,复杂对象(包括原始类型的封装类型,如Integer)是不允许的。另外可以对属性设置默认值,只需在属性后添加default关键字,并赋予一个对应类型的默认值。增加默认机制的好处是,如果接受默认值,则可以省略该属性。
在注解上面添加的注解告诉如何使用该注解。其中比较重要的是@Target和@Retention。
@Target告诉该注解的位置。
@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public @interface Target { ElementType[] value();}
从@Target的定义可以看出,该注解只包含一个数据类型为ElementType的数组的属性。ElementType是一个包含了8个常量的枚举类型。
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, /** Field declaration (includes enum constants) */ FIELD, /** Method declaration */ METHOD, /** Parameter declaration */ PARAMETER, /** Constructor declaration */ CONSTRUCTOR, /** Local variable declaration */ LOCAL_VARIABLE, /** Annotation type declaration */ ANNOTATION_TYPE, /** Package declaration */ PACKAGE}
如果你想要自定义注解放置在方法上,只需将常量ElementType.METHOD放进@Target注解的属性中。
@Target({ElementType.METHOD...})
public @interface MyAnnotation {
...
}
当然,除了可以放在方法上以外,还可以放置到构造器,包,局部变量,参数,类,接口等。在ElementType枚举的常量中,基本上都能从变量名猜出它的作用,不过有两个不是很清楚,它们是ANNOTATION_TYPE和TYPE。TYPE表名注解可以放置到类,接口(包括注解)和枚举上,而ANNOTATION_TYPE(可以想象成是TYPE的子集)只能放置到注解上(比如@Target)。
@Retention注解告诉被注解的注解的驻留时间,该时间是通过RetentionPolicy枚举中的常量来确定。
public enum RetentionPolicy { /** * Annotations are to be discarded by the compiler. */ SOURCE, /** * Annotations are to be recorded in the class file by the compiler * but need not be retained by the VM at run time. This is the default * behavior. */ CLASS, /** * Annotations are to be recorded in the class file by the compiler and * retained by the VM at run time, so they may be read reflectively. * * @see java.lang.reflect.AnnotatedElement */ RUNTIME}
RetentionPolicy包括三个常量,SOURCE,CLASS和RUNTIME。其中默认的是CLASS。
SOURCE告诉该注解的有效范围是源代码。
CLASS告诉该注解的有效范围是源代码和字节码文件。
RUNTIME告诉注解的有效范围是源代码,字节码和JVM运行时。(可以通过反射获取元数据信息)
如果想通过反射机制获取注解的元信息,必须将设置为RUNTIME。
假设将上面的注解添加到MyApplication类上:
@MyAnnotation(name="benson",id=123,hobbies={"basketball","volleyball","bowling"})public class MyApplication {}
那么如何可以获取到上面的数据呢(benson,123,basketball...)
答案是通过反射。前提是该注解的保留决策是RUNTIME类型的。
public static void main(String[] args) {Class myApplication = MyApplication.class;Annotation[] annotations = myApplication.getAnnotations();for(Annotation annotation : annotations) {if(annotation instanceof MyAnnotation) {MyAnnotation myAnnotation = (MyAnnotation) annotation;System.out.println("name:" + myAnnotation.name());System.out.println("id:" + myAnnotation.id());System.out.println("hobbies:" + Arrays.toString(myAnnotation.hobbies()));}}}
打印结果:
name:bensonid:123hobbies:[basketball, volleyball, bowling]
另外,如果一个注解只有一个属性,一个惯例是将该属性的名字设置为value,比如
public @interface MyAnnotation {
String value();
}
这样做的好处是,当你在注解时为该属性提供值时,无须再提供属性名,比如:
@MyAnnotation("happy")
Class ABC {
}
以上等价于
@MyAnnotation(valule="happy")
Class ABC {
}
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- @自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 自定义注解
- 国家集训队论文分类整理
- android 邮件正则表达式
- Posix消息队列的基本操作——创建或打开
- tar 解压缩命令
- hibernate OneToMany,ManyToMany 插入时候出现重复键值异常
- 自定义注解
- linux 信号量之SIGNAL 0
- Python基础10 反过头来看看
- (五)抽象工厂模式详解
- OpenCV学习:Mat类详细解析+源码剖析(四)MSize类和Mstep类
- ExecutorService对象的shutdown()和shutdownNow()的区别
- 图的邻接表表示法及顶点入度、出度的计算方法
- mysql 字符集的问题
- javaweb多行数据提交问题