一.元注解
- @Target:表示该注解可以用于什么地方。可选的ElementType参数包括:
- TYPE:类,接口(包括注解类型),enum的声明。
- FIELD:域的声明(包括enum实例)。
- METHOD:方法的声明。
- PARAMETER:参数的声明。
- CONSTRUCTOR:构造器的声明。
- LOCAL_VARIABLE:局部变量的声明。
- ANNOTATION_TYPE:注解的声明。
- PACKAGE:包的声明。
- SOURCE:注解将被编译器丢弃。
- CLASS:注解在class文件中可用,被VM丢弃。
- RUNTIME:VM会把注解加载到内存里,运行期间可见,所以可以通过反射读取注解的信息。
二.标准注解
J2SE5里内置了三种
- @Override
- @Deprecated
- @SuppressWarnings
三.自定义注解
- 标记注解:没有元素的注解称为标记注解。
- 其它注解:定义了元素的注解。
四.注解元素
自定义一个注解类时,类里面的元素只能是如下类型,如果使用其它类型,编译器报错。
- 所有基本类型(注意不能使用包装类型)
- String
- Class
- enum
- Annotation
- 以上类型的数组
自定义注解
二.代码
- package com.jyz.study.jdk.annotation;
- 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;
- /**
- * 1.演示四种元注解的用法
- * @Target
- * @Retention
- * @Document
- * @Inherited
- *
- * @author JoyoungZhang@gmail.com
- *
- */
- @JyzTargetType
- @JyzRetentionRuntime
- @JyzDocument
- @JyzInherited
- public class MetaAnnotation {
- @JyzTargetField
- private String info;
- @JyzTargetConstructor
- public MetaAnnotation(@JyzTargetParamter String info) {
- this.info = info;
- }
- @JyzTargetMethod
- public void test(){
- @JyzTargetLocalVariable
- String infoInner = "sa";
- }
- }
- @Target(ElementType.TYPE) @interface JyzTargetType{} //接口、类、枚举、注解
- @Target(ElementType.FIELD) @interface JyzTargetField{} //字段、枚举的常量
- @Target(ElementType.METHOD) @interface JyzTargetMethod{} //方法
- @Target(ElementType.PARAMETER) @interface JyzTargetParamter{} //方法参数
- @Target(ElementType.CONSTRUCTOR) @interface JyzTargetConstructor{} //构造函数
- @Target(ElementType.LOCAL_VARIABLE) @interface JyzTargetLocalVariable{} //局部变量
- @Target(ElementType.ANNOTATION_TYPE) @interface JyzTargetAnnotationType{} //注解
- @Target(ElementType.PACKAGE) @Retention(RetentionPolicy.RUNTIME) @interface JyzTargetPackage{public String version() default "";} //包
- @JyzTargetAnnotationType @interface JyzTargetAll{}
- @Retention(RetentionPolicy.SOURCE) @interface JyzRetentionSource{}
- @Retention(RetentionPolicy.CLASS) @interface JyzRetentionClass{}
- @Retention(RetentionPolicy.RUNTIME) @interface JyzRetentionRuntime{}
- @Documented @interface JyzDocument{}
- @Inherited @interface JyzInherited{}
三.代码解释
- Java内置了四种元注解。或许你要问了,这四种元注解又是哪里来的呢?我们来看看这三种元注解,得到的答案是每一种元注解又是建立在四个元注解的基础之上的。有点自己定义自己的意思。
- package java.lang.annotation;
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- public @interface Target {
- ElementType[] value();
- }
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- public @interface Retention {
- RetentionPolicy value();
- }
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- public @interface Documented {
- }
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- public @interface Inherited {
- }
- 什么时候使用这四个元注解?仅仅在你需要定义自己的注解类时,如代码里的Jyz*这些类都是自定义的注解类。
- 什么时候使用自定义注解类或Java内置的几个标准注解类?当然是在普通Java类(指的是不是注解类的类如MetaAnnotation,有时候我也叫它被注解类)里使用。需要记住的是,普通Java类里并不能直接使用元注解,如果你在MetaAnnotation上面加上@Documented,肯定编译报错。
- @Target的八种参数,前六种很好理解,该用什么地方就用什么地方。PACKAGE包的声明会在下文http://zy19982004.iteye.com/blog/1979308单独讲解。于是就是剩下一个ANNOTATION_TYPE了,这个代表了自定义的注解只能用在注解上,看看四个元注解便知,看看
- @JyzTargetAnnotationType @interface JyzTargetAll{}
- @Inherited的作用也在下文说http://zy19982004.iteye.com/blog/1979520。
- @Documented:如果Java普通类里使用@JyzDocumented,则普通Java类的Javadoc里保留@JyzDocumented。
四.使用总结
- 使用四种元注解定义自己的注解类
- @Target(ElementType.?)就根据需要定义吧,不太同意定义成@JyzTargetAll。
- 除非你能保证你的注解类永远被使用在不需要反射的类上,但这个似乎不太可能,所以你最好@Retention(RetentionPolicy.RUNTIME)。
- 至于@Documented也加上吧,对jvm来说完全没什么负担。
- 也建议加上@Inherited,尽管你觉得现在是不需要的,指不定两个被注解类就存在继承关系。
- 为注解类定义需要的属性(上面的Jyz*这些注解类主要是为了演示元注解的使用,并未加上任何元素),并设置默认值。
- 普通Java类里合适的地方使用合适的注解类,并为需要赋值的元素赋值,不赋值将使用默认值。为元素赋值的方式为名-值对,如@JyzTargetPackage(version="1.0") 。如果恰好只需要为一个元素赋值,而这个元素定义为value(),无需使用名值对,只需在括号内给出value元素所需的值即可,如@JyzTargetPackage("1.0") 。