12.3 注解
12.3.1 简介
JDK1.5出现的新特性,一个注解就是一个类,它相当于一种标记,加了注解就等于打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具盒其他程序可以用反射来了解你的类及各种元素上有没有何种标注,有,则采用相应的操作,。标记可以加在包,类,方法,字段,方法的参数以及局部变量上。
几个常见的标记示例:
publicclassAnnotationDemo {
//取消警告
@SuppressWarnings("deprecation")
publicstaticvoidmain(String[] args) {
System.runFinalizersOnExit(true);
}
//当曾经编写的一个方法不好时,可以使用@Deprecated注解来标注已过时。
@Deprecated
publicstaticvoid sayHello() {
System.out.println("hi,传智播客");
}
// HashSet集合中,对象必须覆盖Object类的equals()方法,否则会继续使用Object类的equals()方法进行比较,错误的比较方法。覆盖equals()方法,参数必须一致,为了防止错误写入本类的对象,加入@Override,必须正确覆盖父类方法,不是创建新方法。
@Override
}
12.3.2、应用
在源程序中,调用一个类,这个类会用到注解,需要先准备好注解类,类在调用注解类的对象。注解类的写法类似接口,@interface。先写好注解类A,将注解放在类B中,类C在调用类B时通过反射获得注解类A的内容,进而明确该做什么、不该做什么。可以加上多个注解,加上的实际是注解类的对象:@interfaceA。
1、注解类的应用结构图
注意:main()方法必须放在一个类下,但与这个类不一定有所属关系。
2、元注解
注解类上加的注解,称为“元注解”,元注解有2个:Rentention和Target。对注解类的注解,可以理解为注解类的属性。
⑴、Rentention注解类
注解的生命周期:Java源文件-àclass文件-à内存中的字节码。编译或者运行时,都有可能会取消注解。
Rentention的3种取值意味让注解保留到哪个阶段,RententionPolicy.SOURCE、RententionPoli- cy.CLASS(默认值)、RententionPolicy.RUNTIME。比如@Override、@SuppressWarnings是保留到SOURCE阶段;@Deprecated是保留到RUNTIME阶段。
Rentention相当于注解类的一个属性,因为Rentention的值不同,注解类保留到的阶段不同。注解类内部Rentention的值使用value表示,例如,@Deprecated中,value=Runtime。
Rentention的值是枚举RententionPolicy的值,只有3个:SOURCE、CLASS、RUNTIME。
⑵Target注解类
性质和Rentention一样,都是注解类的属性,表示注解类应该在什么位置,对那一块的数据有效。例如,@Target(ElementType.METHOD)。Target内部的值使用枚举ElementType表示,表示的主要位置有:注解、构造方法、属性、局部变量、方法、包、参数和类(默认值)。多个位置使用数组,例如,@Target
({ElementType.METHOD,ElementType.TYPE})。//为什么是TYPE,而不是class?因为不仅仅只是class类型,还包括其他的类型
技巧:类、接口、枚举、注解这一类事物用TYPE表示,Class的父类,JDK1.5的新特性。
3、注解的基本属性
属性,给注解提供更加详细的信息。注解相当于接口,属性相当于方法。例如,@ItcastAnnotatio -n(color="black"),给属性赋值,取值时类似调用方法,例如,System.out.println(annotation.color -());所有的属性必须全部出现,除非有缺省值。
如果只有value属性,没有其他属性,可以不写=,只针对value,例如,@SuppressWarnings("Depre-cation")。或者有其他属性而且有缺省值,例如,String color() default"blue";,此时value单独出现,不用=。获得注解的属性的值,例如
@ItcastAnnotation(color="red")
publicclass AnnotationDemo {
publicstaticvoid main(String[] args) {
if(AnnotationDemo.class.isAnnotationPresent(ItcastAnnotation.class)){
ItcastAnnotation annotation = (ItcastAnnotation) Annotation.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.color());
}
} }
利用反射获得注解的对象,在让该对象调用属性对应的方法。注意类型转换。
Rentention和Target也是属性,都是value对应的值,值的类型分别是RententionPolicy和ElementType,例如,@Retention(value=RetentionPolicy.RUNTIME)。
4、注解的高级属性
⑴、数组类型的属性
int[] arr() default {3,7,5};,MyAnnotation(arr={3,7,6})。如果数组只有1个元素,可以不加{}。@Target({ElementType.METHOD,ElementType.TYPE})也是数组类型的属性。
⑵、枚举类型的属性
//注解类内部的内容
EnumerationDemo.TrafficLamp lamp() defaultEnumerationDemo.TrafficLamp.RED;
//调用注解的类上
@ItcastAnnotation(lamp=EnumerationDemo.TrafficLamp.YELLOW)
//对注解进行操作
System.out.println(annotation.lamp().nextLamp().name());
⑶、注解类型的属性
将一个注解类作为属性加入到另一个注解类中。
MetaAnnotation annotationAtt() default@MetaAnnotation("Jobs")
@ItcastAnnotation(annotationAtt=@MetaAnnotation("Kim"))
annotation.annotationAtt().value()
注解的返回值可以是8个基本类型、String、Class、枚举以及前面类型的数组,内部还有属性。
需要详细学习注解,可以通过java语言规范,即languagespecification。