注解(Annotation)
概念:
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
4个 基本的Annotation(存在于java.lang包下)
@Override@Deprecated@Suppress Warnings@Safe Varargs(JAVA7新增的)
@Override:限定重写父类方法@Override就是用来指定方法覆盖的,他可以强制一个子类必须覆盖父类的方法。
注意:@Override只能作用于方法,不能作用于其他程序元素
@Deprecated:标示已过时@Deprecated用于标示某个程序元素(类、方法等)已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告。
@SuppressWarnings:抑制编译器警告@SuppressWarnings指示被该Annotation修饰的程序元素(以及该程序元素中的所有子元素)取消显示指定的编译器警告。
存在于java.lang.Annotation中的元注解(用于修饰其他的Annotation定义)
@Documented@Inherited@Retention@Target
@Retention@Retention只能用于修饰一个Annotation定义,用于指定被修饰的Annotation可以保留多长时间。@Retention包含一个RetentionPolicy类型的value成员变量,所以使用@Retention时必须为该Value成员变量指定值。
Value成员变量的值有3个:RetentionPolicy.CLASS:编译器将把Annotation记录在class文件中。当运行java程序时,JVM不在保留Annotation。这是默认值。RetentionPolicy.RUNTIME:编译器将把Annotation记录在class文件中。当运行时java程序,JVM也会保留Annotation,程序可以通过反射获取该Annotation信息。RetentionPolicy.SOURCE:Annotation只保留在源代码中,编译器直接丢弃Annotation。
@Target@Target也只能修饰一个Annotation定义,它用于指定被修饰的Annotation能用于修饰哪些程序单元。
其value成员变量的值:ElementType.ANNOTATON_TYPE:指定该策略的Annotation只能修饰Annotation。ElementType.CONSTRUCTOR:指定该策略的Annotation只能修饰构造函数ElementType.FIELD:指定该策略的Annotation只能修饰成员变量ElementType.LOCAL_VARIABLE:指定该策略的Annotation只能修饰局部变量ElementType.METHOD:指定该策略的Annotation只能修饰方法ElementType.PACKAGE:指定该策略的Annotation只能修饰包ElementType.PARAMETER:指定该策略的Annotation可以修饰参数ElementType.TYPE:指定该策略的Annotation可以修饰类、接口(包括注释类型)或枚举
@Documented@Documented用于指定被该元Annotation修饰的Annotation类将被javadoc工具提取成文档,如果定义Annotation类时使用了@Documented修饰,则所有使用该Annotation秀水的程序元素的API文档中将会包含该Annotation说明。
@Inherited@Inherited元Annotation指定被他修饰的Annotation将具有继承性——如果某个类使用了@Annotation(定义该Annotation时使用了@Inherited修饰)修饰,则其子类将自动被@Annotation修饰
注解的应用结构图:
基础应用:使用反射技术获取Annotation信息
前提:元注解Retention的value值必须是RetentionPolicy.RUNTIME
代码示例:
注解代码:
package cn.itheima.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)//元注解
public @interface MyAnnotation
{
}
获取注解信息:
package cn.itheima.Annotation;
@MyAnnotation//将注解应用到类上
public class AnnotationTest
{
/**
* @param args
*/
public static void main(String[] args)
{
// 获取注解信息
//判断AnnotationTest的字节码文件中是否存在MyAnnotation注解
if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class))
{
//输出注解信息
//注意:元注解Retention的value值必须是RetentionPolicy.RUNTIME否则返回值为null
System.out.println((MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class));
}
}
}
总结:
使用到的方法体系
java.lang.Class
|--boolean isAnnotationPresent(Class annotationclass) 如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。|--<A extends Annotation> A getAnnotation(Class<A> annotationClass) 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
注解生命周期的三个阶段:1,源文件 2,class文件 3,内存中的字节码
@Override --> SOURCE
@Deprecated--> RUNTIME
@Suppress Warnings-->SOURCE
为注解增加基本属性
什么是注解的属性
一个注解相当于一个胸牌,如果你胸前贴了胸牌,就是传智播客的学生,否则,就不是。如果还想区分出是传智播客哪个班的学生,这时候可以为胸牌在增加一个属性来进行区分。加了属性的标记效果为:@MyAnnotation(color="red")
定义基本类型的属性和应用属性:
在注解类中增加String color();@MyAnnotation(color="red")
用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法
MyAnnotation a = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);System.out.println(a.color());可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象
为属性指定缺省值:
String color() default "yellow";
value属性:
String value() default "zxx";如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你只有一个value属性),那么可以省略value=部分,例如:@MyAnnotation("lhm")。
数组类型的属性
int [] arrayAttr() default {1,2,3};@MyAnnotation(arrayAttr={2,3,4})如果数组属性中只有一个元素,这时候属性值部分可以省略大括
枚举类型的属性
EnumTest.TrafficLamp lamp() ;@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
注解类型的属性:
MetaAnnotation annotationAttr() default @MetaAnnotation("xxxx");@MyAnnotation(annotationAttr=@MetaAnnotation(“yyy”) )可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象,同样的道理,可以认为上面这个@MetaAnnotation是MetaAnnotation类的一个实例对象,调用代码如下:MetaAnnotation ma = myAnnotation.annotationAttr();System.out.println(ma.value());
代码示例:
枚举:
package cn.itheima.Annotation;
public enum Lamp
{
GREEN,RED,YELLOW;
}
增加属性的注解:
package cn.itheima.Annotation;
public @interface MetaAnnotation
{
String value();
}
注解:
package cn.itheima.Annotation;
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.TYPE,ElementType.METHOD})
public @interface MyAnnotation
{
//定义类型
String color();
String value();
int[] arr();
Lamp lamp();
MetaAnnotation metaAnnotation();
}
测试代码
//将注解应用到类上
@MyAnnotation(color = "green", value = "123",arr = {1,2,3},lamp = Lamp.RED,metaAnnotation = @MetaAnnotation("Hello"))
public class AnnotationTest
{
/**
* @param args
*/
public static void main(String[] args)
{
// 获取注解信息
//判断AnnotationTest的字节码文件中是否存在MyAnnotation注解
if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class))
{
//输出注解信息
//注意:元注解Retention的value值必须是RetentionPolicy.RUNTIME否则返回值为null
MyAnnotation annotation = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(annotation);
//基本类型
System.out.println(annotation.color());
//value值
System.out.println(annotation.value());
//数组类型
System.out.println(annotation.arr().length);
//枚举类型
System.out.println(annotation.lamp());
//注解类型
System.out.println(annotation.metaAnnotation());
}
}
}
注意注解中各类型的定义方法和赋值方法