RetentionPolicy 是一个枚举类型,有三个值:SOURCE、CLASS 、  RUNTIME 分别对应着Java源文件、class文件、内存中的字节码
  我们在重新看下上个代码,AnimTest 没有声明Retention,故保留默认的CLASS,只保留到编译时期。所以内存中加载类文件时,注解类已被清除,所以才会找不到AnimTest注解类的标记。要想在反射中能找到该标记,只要设置下注解类的保留周期,所以接着改下这个注解类
/**
* 自定义注解类
* @author Administrator
*
*/
@Retention(value = RetentionPolicy.RUNTIME)     //表示运行时也保留该注解类
public @interface AnimTest {
}
  在执行代码,结果是:it  has  one
  3、现在有个问题,是注解类的使用范围是怎样的呢?只能在类上么?
  其实有个元注释Tagert来限定范围的。Tagert 指的是注释类型所适用的程序元素的种类。如果注释类没有声明Tagert元注释,则可以适用于任何元素上,如果声明了,编译器会强制实施指定的范围
  如果要使AnimTest只作用于方法上,则在注释类声明Tagert
/**
* 自定义注解类
* @author Administrator
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})    //限定范围,作用于方法
public @interface AnimTest {
}
  那么这个注解类不能作用于类上了,否则会编译异常,只能作用于方法上,代码如下:
public class ZhujieTest {
/**
* @param args
*/
@AnimTest  //作用于方法上
public static void main(String[] args) {
boolean isAnim  = ZhujieTest.class.isAnnotationPresent(AnimTest.class);
if(isAnim)
System.out.println("it  has one");
else
System.out.println("no have");
}
}
  如果注释类既可以使用类上也可以作用 于方法上,只要修改为 @Target(value = {ElementType.METHOD,ElementType.TYPE}),type是表示类型
  三、为注解增加各种属性
  1、现在给注解类添加各种属性,类似接口形式,只提供方法
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.itcast.classdemo.WeekDay;
/**
* 自定义注解类
* @author Administrator
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD,ElementType.TYPE,ElementType.ANNOTATION_TYPE})
public @interface AnimTest {
String color();   //字符串
int count();    //整型
int[] arr();   //数组
MetaAnnotation meta() default @MetaAnnotation("very food");  //注释类型
WeekDay day() default WeekDay.MON;   //枚举类型
}
//注释类
public @interface MetaAnnotation {
String value() default "heollo";    //提供默认值
}
//枚举类
public enum WeekDay {
SUN,MON
}
  2、以下是测试注释类调用属性
import com.itcast.zhujie.AnimTest;
@AnimTest (color ="red",count =1,arr=234)   //这是自定义的注解,并为其属性赋值
public class ZhujieTest {
/**
* @param args
*/
@AnimTest (color ="blue",count=2,arr={3,21})
public static void main(String[] args) {
//是否含有AnimTest注释标记
boolean isAnim  = ZhujieTest.class.isAnnotationPresent(AnimTest.class);
if(isAnim){
//获取AnimTest注释标记对象
AnimTest an = ZhujieTest.class.getAnnotation(AnimTest.class);
//以下都是获取AnimTest注释标记对象的属性
System.out.println(an.color());  // red
System.out.println(an.count());   //1
System.out.println(Arrays.toString(an.arr()));   //[234]
System.out.println(an.meta().value());   //very good
System.out.println(an.day());            //MON
System.out.println("it  has one");
}else
System.out.println("no have");
}
}
  经上述测试总结:
  1)注释类的属性可以有String、int、数组、枚举和注解
  2)注释类的属性可以设置默认值,如String color() default "red";
  3)在使用注释类时,有属性,但没默认值,这时必须要赋值,否则编译不通                过 @AnimTest (color ="blue",count=2,arr={3,21})
  4)获取类上的注释对象,用反射技术AnimTest an = ZhujieTest.class.getAnnotation(AnimTest.class);
  5)获取注释上的属性,类似调用方法一样,需要带括号;
  6)如果注释类只有一个属性要赋值,且属性名为value,则赋值时属性名和等号都可以省略,如:@MetaAnnotation("very food")