转载:转自大牛 https://www.cnblogs.com/xdp-gacl/p/3622275.html 孤傲苍狼
注解(Annotation)很重要,未来的开发模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,现在的Struts2有一部分也是基于注解的了,注解是一种趋势,现在已经有不少的人开始用注解了,注解是JDK1.5之后才有的新特性
JDK1.5之后内部提供的三个注解
@Deprecated 意思是“废弃的,过时的”
@Override 意思是“重写、覆盖”
@SuppressWarnings 意思是“压缩警告”
范例:注解的应用:
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码
总结:注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,没有加,则等于没有任何标记,以后,javac编译器、开发工具和其他程序可以通过反射来了解你的类及各种元素上有无何种标记,看你的程序有什么标记,就去干相应的事,标记可以加在包、类,属性、方法,方法的参数以及局部变量上。
注解就相当于一个你的源程序要调用一个类,在源程序中应用某个注解,得事先准备好这个注解类。就像你要调用某个类,得事先开发好这个类。
自定义一个最简单的注解:
1 public @interface MyAnnotation{}
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码
把自定义的注解加到某个类上:
1 @ MyAnnotation 2 public class AnnotationUse{ 3 4 }
用反射测试进行测试AnnotationUse的定义上是否有@MyAnnotation
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码
根据反射的测试的问题,引出@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.)
下面看看@Deprecated、@Override、@SuppressWarnings这三个注解的@Retention注解的属性值分别是什么吧
Java API中是这样定义的@Deprecated的
1 @Documented 2 @Retention(value=RUNTIME) 3 public @interface Deprecated
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
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
注解可以看成是一种特殊的类,既然是类,那自然可以为类添加属性
语法:类型 属性名();
1 package cn.gacl.annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Retention(RetentionPolicy.RUNTIME) 9 //Retention注解决定MyAnnotation注解的生命周期 10 @Target( { ElementType.METHOD, ElementType.TYPE }) 11 public @interface MyAnnotation { 12 /** 13 * 定义基本属性 14 * @return 15 */ 16 String color(); 17 }
其实从代码的写法上来看,注解更像是一种特殊的接口,注解的属性定义方式就和接口中定义方法的方式一样,而应用了注解的类可以认为是实现了这个特殊的接口
1 package cn.gacl.annotation; 2 3 @MyAnnotation(color="red")//应用MyAnnotation注解的color属性 4 public class MyAnnotationTest { 5 public static void main(String[] args) { 6 /** 7 * 用反射方式获得注解对应的实例对象后,在通过该对象调用属性对应的方法 8 */ 9 MyAnnotation annotation = (MyAnnotation) MyAnnotationTest.class.getAnnotation(MyAnnotation.class); 10 System.out.println(annotation.color());//输出red 11 } 12 }
语法:类型 属性名() default 默认值;
package cn.gacl.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) //Retention注解决定MyAnnotation注解的生命周期 @Target( { ElementType.METHOD, ElementType.TYPE }) public @interface MyAnnotation { String color() default "blue";//为属性指定缺省值 }
1 package cn.gacl.annotation; 2 3 @MyAnnotation 4 public class MyAnnotationTest { 5 public static void main(String[] args) { 6 /** 7 * 用反射方式获得注解对应的实例对象后,在通过该对象调用属性对应的方法 8 */ 9 MyAnnotation annotation = (MyAnnotation) MyAnnotationTest.class.getAnnotation(MyAnnotation.class); 10 System.out.println(annotation.color());//输出color属性的默认值:blue 11 12 } 13 }
如果一个注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你只有一个value属性),那么可以省略掉“value=”部分。
例如:@SuppressWarnings("deprecation")
1 package cn.gacl.annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Retention(RetentionPolicy.RUNTIME) 9 //Retention注解决定MyAnnotation注解的生命周期 10 @Target( { ElementType.METHOD, ElementType.TYPE }) 11 public @interface MyAnnotation { 12 String color() default "blue";//为属性指定缺省值 13 String value();//定义一个名称为value的属性 14 }
1 package cn.gacl.annotation; 2 3 @MyAnnotation("孤傲苍狼")//等价于@MyAnnotation(value="孤傲苍狼") 4 public class MyAnnotationTest { 5 public static void main(String[] args) { 6 /** 7 * 用反射方式获得注解对应的实例对象后,在通过该对象调用属性对应的方法 8 */ 9 MyAnnotation annotation = (MyAnnotation) MyAnnotationTest.class.getAnnotation(MyAnnotation.class); 10 System.out.println(annotation.color());//输出color属性的默认值:blue 11 System.out.println(annotation.value()); 12 13 } 14 }
1 /** 2 * MetaAnnotation注解类为元注解 3 * @author 孤傲苍狼 4 * 5 */ 6 public @interface MetaAnnotation { 7 String value();//元注解MetaAnnotation设置有一个唯一的属性value 8 }
为注解添加一个注解类型的属性,并指定注解属性的缺省值:MetaAnnotation annotationAttr() default @MetaAnnotation("xdp");
EumTrafficLamp.java
1 package cn.gacl.annotation; 2 /** 3 * 交通信号灯颜色枚举 4 * @author 孤傲苍狼 5 * 6 */ 7 public enum EumTrafficLamp { 8 RED,//红 9 YELLOW,//黄 10 GREEN//绿 11 }
MetaAnnotation.java
1 /** 2 * MetaAnnotation注解类为元注解 3 * @author 孤傲苍狼 4 * 5 */ 6 public @interface MetaAnnotation { 7 String value();//元注解MetaAnnotation设置有一个唯一的属性value 8 }
MyAnnotation.java
1 package cn.gacl.annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Retention(RetentionPolicy.RUNTIME) 9 //Retention注解决定MyAnnotation注解的生命周期 10 @Target({ElementType.METHOD, ElementType.TYPE}) 11 public @interface MyAnnotation { 12 String color() default "blue";//为属性指定缺省值 13 /** 14 * 为注解添加value属性,这个value属性很特殊,如果一个注解中只有一个value属性要设置, 15 * 那么在设置注解的属性值时,可以省略属性名和等号不写, 直接写属性值,如@SuppressWarnings("deprecation"), 16 * 这里的MyAnnotation注解设置了两个String类型的属性,color和value, 17 * 因为color属性指定有缺省值,value属性又是属于特殊的属性,因此使用MyAnnotation注解时 18 * 可以这样使用MyAnnotation注解:"@MyAnnotation(color="red",value="xdp")" 19 * 也可以这样使用:"@MyAnnotation("孤傲苍狼")",这样写就表示MyAnnotation注解只有一个value属性要设置,color属性采用缺省值 20 * 当一个注解只有一个value属性要设置时,是可以省略"value="的 21 */ 22 String value();//定义一个名称为value的属性 23 //添加一个int类型数组的属性 24 int[] arrayAttr() default {1,2,4}; 25 //添加一个枚举类型的属性,并指定枚举属性的缺省值,缺省值只能从枚举类EumTrafficLamp中定义的枚举对象中取出任意一个作为缺省值 26 EumTrafficLamp lamp() default EumTrafficLamp.RED; 27 //为注解添加一个注解类型的属性,并指定注解属性的缺省值 28 MetaAnnotation annotationAttr() default @MetaAnnotation("xdp"); 29 30 }
MyAnnotationTest.java
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码
分类: Java基础加强总结