一、了解注解及java提供的几个基本注解
注解是JDK1.5的新特性,是用于向开发工具(javac编译器)传递消息的,一个注解代表一个类,创建注解就相当于创建了这个类的实例对象。
Java的基本注解:
在java.lang包,可看到JDK提供的最基本的annotation
@SuppressWarnings("deprecation") 用于抑制过时的警告信息。@Deprecated 用于标识已作废的类(过时)。
@Override 检查覆写父类或接口的方法的正确性。
总结:注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去做相应的事。标记可以加在包,类,字段,方法,方法的参数,局部变量以及成员变量上。
二、注解的定义
2.1注解的定义流程
定义注解类--->应用了”注解类”的类--->对“应用了注解类的类”进行反射操作的类。
注解就相当于一个你的源程序中要调用的一个类,要在源程序中应用某个注解,得先准备好了这个注解类。就像你要调用某个类,得先开发好这个类一样。
例:自定义注解,通过反射打印该注解
package cn.itcast.day2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
}
package cn.itcast.day2;
@ItcastAnnotation
public class AnnotationTest {
@ItcastAnnotation
public static void main(String[] args) {
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){
ItcastAnnotation annotation = AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation);
}
}
}
分析:自定义注解的生命周期,默认值在RetetionPolicy.CLASS (class文件)阶段。只有把元注解设置为RUNTIME运行时阶段,加载到内存中,才会有字节码,才能发现自定义注解。
2.2 @Retention
@Retention是元注解(注解的注解),指示注释类型的注释要保留多久(生命周期)。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。
RetentionPolicy是枚举,对应三个常量值:SOURCER、CLASS、RUNTIME
这三种值分别对应:Java源文件-->class文件-->内存中的字节码。
2.3 java三个基本的注解对应的属性值
@Override的属性值是SOURCE,因为是给编译器检查的,所以在SOURCE阶段)
@SuppressWarnings的属性值是SOURCE
@Deprecated的属性值是RUNTIME,因为调用别人的类,只有把类加载到内存中才能读取字节码,才知道有过时的类。
@Target注解用于确定定义的注解运用在哪种成分上,指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。
ElementType枚举常量值中有个TYPE,这个值表示只要是类、接口都可以。
只有元注释类型直接用于注释时,Target 元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。
三、为注解增加基本属性
3.1什么是注解的属性
一个注解很像一个接口,注解里的属性很像一个抽象方法,属性就是对注解更进一步描述。
3.2定义基本类型的属性
1、为属性指定缺省值:String color() default “red”;
2、value属性:如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你只有一个value属性),那么可以省略”value=”部分,例如:@MyAnnotation(“xxx”)
3.2为注解增加高级属性
注解的属性的返回值类型可以是:八个基本数据类型、String类型、Class类型、枚举类型、注解类型。
1、数组类型的属性
int[] arrayAttr() default{1,2,3};
@MyAnnotation(arrayAttr={3,5,6})
如果数组属性中只有一个元素,这时候属性值部分可以省略大括号。
2、枚举类型的属性
EnumTest.TrafficLamp lamp();
@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
注:枚举和注解都是特殊的类, 不能用new创建它们的实例对象,创建枚举的实例对象就是在其中增加元素。
3、注解类型的属性
MetaAnnotation annotationAttr() default @MetaAnnotation(“xxx”);
@MyAnnotation(anotationAttr=@MetaAnnotation(“yyy”))
可以认为上面这个@MyAnnotation是MyAnnotation类的一个实例对象,那么也可以认为@MetaAnnotation是MetaAnnotation类的一个实例对象。
例:
package cn.itcast.day2;
public @interface MetaAnnotation {
String value();
}
package cn.itcast.day2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cn.itcast.day1.EnumTest;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
String color() default "red";//设置默认值
String value();
int[] arrayAttr() default{1,2,3};//数组类型的属性
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;//枚举类型的属性
MetaAnnotation annotationAttr() default @MetaAnnotation("123");//指定注解类型属性的默认值
}
package cn.itcast.day2;
//分别对这些类型的属性设置值
@ItcastAnnotation(annotationAttr=@MetaAnnotation("zj"),arrayAttr={2,3,6},color="green",value="abc")
public class AnnotationTest {
//给value()设置值的简写形式
@ItcastAnnotation("def")
public static void main(String[] args)throws Exception {
//判断AnnotationTest.class类对象如果有ItcastAnnotation类型的注解,则做出如下处理
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){
//获取得ItcastAnnotation注解类对象
ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.value());//打印value属性值
System.out.println(annotation.arrayAttr().length);//打印数组长度
System.out.println(annotation.lamp().nextLamp().name());//打印RED返回下个灯的名称
System.out.println(annotation.annotationAttr().value());//打印属性是注解类型的值
}
}
}