一,概念:
注解是 JDK5 引入的新特性,最初衍生自代码注释,但现在早已经超出了注释的范畴,以至于我很惶恐,不敢使用注释这个词汇来描述他,尽管现有的很多资料里仍然称其为注释。如果说反射使得很多技术实现(动态代理、依赖注入等)有了基础,那么注解就是使这些技术实现变得平民化的基础。
从 class 文件规范中可以看出, JDK5 开始, class 文件已经引入了注解描述片段。站在 java 虚拟机的角度来看, class 保留和运行时保留的注解已经和 java 二进制码放在了同等的地位。虚拟机在加载 class 文件时,会为注解内容分配空间并进行解析,最终还会为注解和对应的二进制码建立关联。尽管这些注解不会被运行,但其对代码的说明能力,结合反射技术已经足够我们做太多的事情。
我们知道, java 除了内置的注解( @Override 、 @Deprecated 等)以外,还支持自定义注解( Struts 、 Hibernate 等很多框架甚至 java 自身都实现了很多自定义注解)。当然,更为厉害的是元注解,元注解是用来描述注解的注解。
要实现一个自定义注解,必须通过 @interface 关键字来定义。且在 @interface 之前,需要通过元注解来描述该注解的使用范围( @Target )、生命周期( @Retention )及其他(其他的不重要)
@Target 用于描述注解的使用范围(即:被描述的注解可以用在什么地方),其取值有:
取值 | 描述 |
CONSTRUCTOR | 用于描述构造器 |
FIELD | 用于描述域 |
LOCAL_VARIABLE | 用于描述局部变量 |
METHOD | 用于描述方法 |
PACKAGE | 用于描述包 |
PARAMETER | 用于描述参数 |
TYPE | 用于描述类或接口(甚至 enum ) |
@Retention 用于描述注解的生命周期(即:被描述的注解在什么范围内有效),其取值有:
取值 | 描述 |
SOURCE | 在源文件中有效 |
CLASS | 在 class 文件中有效 |
RUNTIME | 在运行时有效(即运行时保留 常用) |
下面直接看例子:
首先定义几种不同类型的注解方式
1,作用于类上面的
@Target(ElementType.TYPE)//用于描述类或接口@Retention(RetentionPolicy.RUNTIME)public @interface MyClassAnnotation { String uri(); String desc(); }
2,作用于字段上面的
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface MyFieldAnnotation { String uri(); String desc(); }
3,作用于构造上面的
@Target(ElementType.CONSTRUCTOR)@Retention(RetentionPolicy.RUNTIME)public @interface MyConstructorAnnotation { String uri(); String desc(); }
4,作用于方法上面
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface MyMethodAnnotation { String uri(); String desc(); }
通过实例看看怎么使用吧....
public class MyAllAnnotationTest { @SuppressWarnings("unchecked") public static void main(String[] args) { MySample sample = new MySample(); Class clazz = sample.getClass(); //类 boolean c = clazz.isAnnotationPresent(MyClassAnnotation.class); if (c) { MyClassAnnotation myClassAnnotation = (MyClassAnnotation) clazz.getAnnotation(MyClassAnnotation.class); printMyClassAnnotation(myClassAnnotation); } //构造 Constructor[] constructors = clazz.getConstructors(); for (Constructor constructor : constructors) { boolean cc = constructor.isAnnotationPresent(MyConstructorAnnotation.class); if (cc) { MyConstructorAnnotation myConstructorAnnotation = (MyConstructorAnnotation) constructor.getAnnotation(MyConstructorAnnotation.class); printMyConstructorAnnotation(myConstructorAnnotation); } } //字段 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { boolean f = field.isAnnotationPresent(MyFieldAnnotation.class); if (f) { MyFieldAnnotation myFieldAnnotation = (MyFieldAnnotation)field.getAnnotation(MyFieldAnnotation.class); printMyFieldAnnotation(myFieldAnnotation); } } //方法 Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { boolean m = method.isAnnotationPresent(MyMethodAnnotation.class); if (m) { MyMethodAnnotation methodAnnotation = (MyMethodAnnotation)method.getAnnotation(MyMethodAnnotation.class); printMyMethodAnnotation(methodAnnotation); } } } public static void printMyClassAnnotation(MyClassAnnotation myClassAnnotation){ if (null == myClassAnnotation) { return; } System.out.println("url = " + myClassAnnotation.url()); System.out.println("desc = " + myClassAnnotation.desc()); } public static void printMyConstructorAnnotation(MyConstructorAnnotation myConstructorAnnotation){ if (null == myConstructorAnnotation) { return; } System.out.println("url = " + myConstructorAnnotation.url()); System.out.println("desc = " + myConstructorAnnotation.desc()); } public static void printMyFieldAnnotation(MyFieldAnnotation myFieldAnnotation){ if (null == myFieldAnnotation) { return; } System.out.println("url = " + myFieldAnnotation.url()); System.out.println("desc = " + myFieldAnnotation.desc()); } public static void printMyMethodAnnotation(MyMethodAnnotation methodAnnotation){ if (null == methodAnnotation) { return; } System.out.println("url = " + methodAnnotation.url());}
打印结果如下所示:
url = cn.cd.sg.test.reflect.MySampledesc = The Class Name For MySampleurl = cn.cd.sg.test.reflect.MySample#MySample For Constructordesc = The default constuctor Name For MySample()url = cn.cd.sg.test.reflect.MySample#iddesc = The Field Name For Idurl = cn.cd.sg.test.reflect.MySample#namedesc = The Field Name For Nameurl = cn.cd.sg.test.reflect.MySample#setIddesc = The Mrthod Name For setId()url = cn.cd.sg.test.reflect.MySample#getNamedesc = The Mrthod Name For getName()url = cn.cd.sg.test.reflect.MySample#getIddesc = The Mrthod Name For getId()url = com.sg.annotation.MySample#setNamedesc = The Mrthod Name For setName()
以上就是JAVA自定义注解的一个小例子,深入的在去研究,先入个门再说,呵呵........