一、认识注解
注解(Annotation)很重要,未来的开发模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,现在的Struts2有一部分也是基于注解的了,注解是一种趋势,现在已经有不少的人开始用注解了,注解是JDK1.5之后才有的新特性
JDK1.5之后内部提供的三个注解
@Deprecated 意思是“废弃的,过时的”
@Override 意思是“重写、覆盖”
@SuppressWarnings 意思是“压缩警告”
范例:注解的应用:
1 package cn.itcast.day2; 2 /** 3 * 此类是用来演示注解(Annotation)的应用的,注解也是JDK1.5新增加的特性之一 4 * JDK1.5内部提供的三种注解是:@SuppressWarnings(":deprecation")、@Deprecated、@Override 5 * @author 孤傲苍狼 6 * 7 */ 8 /** 9 * 类名的命名是有讲究的,类名、属性名、变量名一般是名词,或者是形容词+名词,方法一般是动词,或者是动词+名词, 10 * 以AnnotationTest作为类名和以TestAnnotation作为类名是有区别的, 11 * 前者是注解的测试,符合名词的特征,后者是测试注解,听起来就是一个动作名称,是方法的命名特征 12 */ 13 public class AnnotationTest { 14 /** 15 * @param args 16 */ 17 @SuppressWarnings(":deprecation") 18 //这里就是注解,称为压缩警告,这是JDK内部自带的一个注解,一个注解就是一个类,在这里使用了这个注解就是创建了SuppressWarnings类的一个实例对象 19 public static void main(String[] args) { 20 System.runFinalizersOnExit(true); 21 //The method runFinalizersOnExit(boolean) from the type System is deprecated(过时的,废弃的) 22 //这里的runFinalizersOnExit()方法画了一条横线表示此方法已经过时了,不建议使用了 23 } 24 @Deprecated //这也是JDK内部自带的一个注解,意思就是说这个方法已经废弃了,不建议使用了 25 public static void sayHello(){ 26 System.out.println("hi,孤傲苍狼"); 27 } 28 @Override //这也是JDK1.5之后内部提供的一个注解,意思就是要重写(覆盖)JDK内部的toString()方法 29 public String toString(){ 30 return "孤傲苍狼"; 31 } 32 }
总结:注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,没有加,则等于没有任何标记,以后,javac编译器、开发工具和其他程序可以通过反射来了解你的类及各种元素上有无何种标记,看你的程序有什么标记,就去干相应的事,标记可以加在包、类,属性、方法,方法的参数以及局部变量上。
注解就相当于一个你的源程序要调用一个类,在源程序中应用某个注解,得事先准备好这个注解类。就像你要调用某个类,得事先开发好这个类。
自定义一个最简单的注解:
1 public @interface MyAnnotation{}
1 package cn.itcast.day2; 2 import java.lang.annotation.ElementType; 3 import java.lang.annotation.Retention; 4 import java.lang.annotation.RetentionPolicy; 5 import java.lang.annotation.Target; 6 /** 7 * 这是一个自定义的注解(Annotation)类 在定义注解(Annotation)类时使用了另一个注解类Retention 8 * 在注解类上使用另一个注解类,那么被使用的注解类就称为元注解 9 * 10 * @author 孤傲苍狼 11 * 12 */ 13 @Retention(RetentionPolicy.RUNTIME) 14 //Retention注解决定MyAnnotation注解的生命周期 15 @Target( { ElementType.METHOD, ElementType.TYPE }) 16 //Target注解决定MyAnnotation注解可以加在哪些成分上,如加在类身上,或者属性身上,或者方法身上等成分 17 /* 18 * @Retention(RetentionPolicy.SOURCE) 19 * 这个注解的意思是让MyAnnotation注解只在java源文件中存在,编译成.class文件后注解就不存在了 20 * @Retention(RetentionPolicy.CLASS) 21 * 这个注解的意思是让MyAnnotation注解在java源文件(.java文件)中存在,编译成.class文件后注解也还存在, 22 * 被MyAnnotation注解类标识的类被类加载器加载到内存中后MyAnnotation注解就不存在了 23 */ 24 /* 25 * 这里是在注解类MyAnnotation上使用另一个注解类,这里的Retention称为元注解。 26 * Retention注解括号中的"RetentionPolicy.RUNTIME"意思是让MyAnnotation这个注解的生命周期一直程序运行时都存在 27 */ 28 public @interface MyAnnotation { 29 }
把自定义的注解加到某个类上:
1 @ MyAnnotation 2 public class AnnotationUse{ 3 4 }
用反射测试进行测试AnnotationUse的定义上是否有@MyAnnotation
1 package cn.itcast.day2; 2 @MyAnnotation 3 //这里是将新创建好的注解类MyAnnotation标记到AnnotaionTest类上 4 public class AnnotationUse { 5 public static void main(String[] args) { 6 // 这里是检查Annotation类是否有注解,这里需要使用反射才能完成对Annotation类的检查 7 if (AnnotationUse.class.isAnnotationPresent(MyAnnotation.class)) { 8 /* 9 * MyAnnotation是一个类,这个类的实例对象annotation是通过反射得到的,这个实例对象是如何创建的呢? 10 * 一旦在某个类上使用了@MyAnnotation,那么这个MyAnnotation类的实例对象annotation就会被创建出来了 11 * 假设很多人考驾照,教练在有些学员身上贴一些绿牌子、黄牌子,贴绿牌子的表示送礼送得比较多的, 12 * 贴黄牌子的学员表示送礼送得比较少的,不贴牌子的学员表示没有送过礼的,通过这个牌子就可以标识出不同的学员 13 * 教官在考核时一看,哦,这个学员是有牌子的,是送过礼给他的,优先让有牌子的学员过,此时这个牌子就是一个注解 14 * 一个牌子就是一个注解的实例对象,实实在在存在的牌子就是一个实实在在的注解对象,把牌子拿下来(去掉注解)注解对象就不存在了 15 */ 16 MyAnnotation annotation = (MyAnnotation) AnnotationUse.class 17 .getAnnotation(MyAnnotation.class); 18 System.out.println(annotation);// 打印MyAnnotation对象,这里输出的结果为:@cn.itcast.day2.MyAnnotation() 19 } 20 } 21 }
根据反射的测试的问题,引出@Retention元注解的讲解:其三种取值:RetentionPolicy.SOURCE、RetentionPolicy.CLASS、RetentionPolicy.RUNTIME分别对应:Java源文件(.java文件)---->.class文件---->内存中的字节码
当在Java源程序上加了一个注解,这个Java源程序要由javac去编译,javac把java源文件编译成.class文件,在编译成class时可能会把Java源程序上的一些注解给去掉,java编译器(javac)在处理java源程序时,可能会认为这个注解没有用了,于是就把这个注解去掉了,那么此时在编译好的class中就找不到注解了, 这是编译器编译java源程序时对注解进行处理的第一种可能情况,假设java编译器在把java源程序编译成class时,没有把java源程序中的注解去掉,那么此时在编译好的class中就可以找到注解,当程序使用编译好的class文件时,需要用类加载器把class文件加载到内存中,class文件中的东西不是字节码,class文件里面的东西由类加载器加载到内存中去,类加载器在加载class文件时,会对class文件里面的东西进行处理,如安全检查,处理完以后得到的最终在内存中的二进制的东西才是字节码,类加载器在把class文件加载到内存中时也有转换,转换时是否把class文件中的注解保留下来,这也有说法,所以说一个注解的生命周期有三个阶段:java源文件是一个阶段,class文件是一个阶段,内存中的字节码是一个阶段,javac把java源文件编译成.class文件时,有可能去掉里面的注解,类加载器把.class文件加载到内存时也有可能去掉里面的注解,因此在自定义注解时就可以使用Retention注解指明自定义注解的生命周期,自定义注解的生命周期是在RetentionPolicy.SOURCE阶段(java源文件阶段),还是在RetentionPolicy.CLASS阶段(class文件阶段),或者是在RetentionPolicy.RUNTIME阶段(内存中的字节码运行时阶段),根据JDK提供的API可以知道默认是在RetentionPolicy.CLASS阶段 (JDK的API写到:the retention policy defaults to RetentionPolicy.CLASS.)
1、@Deprecated
Java API中是这样定义的@Deprecated的
1 @Documented 2 @Retention(value=RUNTIME) 3 public @interface Deprecated
2、@Override
Java API中是这样定义的@Override的
1 @Target(value=METHOD) 2 @Retention(value=SOURCE) 3 public @interface Override
@Override是给javac(java编译器)看的,编译完以后就@Override注解就没有价值了,@Override注解在源代码中有用,编译成.class文件后@Override注解就没有用了,因此@Override的Retention的属性值是RetentionPolicy.SOURCE
3、@SuppressWarnings
Java API中是这样定义的@SuppressWarnings的
1 @Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE}) 2 @Retention(value=SOURCE) 3 public @interface SuppressWarnings
@SuppressWarnings是给javac(java编译器)看的,编译器编译完java文件后,@SuppressWarnings注解就没有用了,所以@SuppressWarnings的Retention的属性值是RetentionPolicy.SOURCE
@Target元注解决定了一个注解可以标识到哪些成分上,如标识在在类身上,或者属性身上,或者方法身上等成分,@Target默认值为任何元素(成分)
例如:
1 @Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE}) 2 @Retention(value=SOURCE) 3 public @interface SuppressWarnings
未完待续.....
注解(Annotation)的应用,布布扣,bubuko.com
原文:http://www.cnblogs.com/xdp-gacl/p/3622275.html