注解开发
注解不仅包含了元数据,它还可以作用于程序运行过程中、注解解释器可以通过注解决定程序的执行顺序
Java提供了三种内建注解
- @Override - 标注在方法上 , 表示该方法是用于重写 , 非重写则报错
- @Deprecated - 标注在方法上 , 表示该方法已过时 , 不推荐使用 , 但仍然是可以使用的
- @SuppressWarnings - 告诉编译器忽略特定的警告信息
创建自定义注解和创建一个接口类似 , 但是要在interface前面加上@符号
注解的定义有一些限制
- 注解方法不能带参数
- 注解方法的返回值类型可以是 : 基本类型 , String , Enums , Annotation 或者是这些类型的对应数组
以下面这个注解定义的为例
1 @Documented//拥有这个注解的元素可以被javadoc文档化 2 @Target(ElementType.METHOD) 3 //该注解可以注解的程序元素返回,不添加则表示可以注解任何程序元素 4 @Inherited//该注解类型被自动继承 5 @Retention(RetentionPolicy.RUNTIME) 6 //指明该注解被保留的时间长短 7 public @interface InfoMethod { 8 String author() default "sookie" ; 9 String date(); 10 int version() default 1; 11 String comments(); 12 }
从中可以看出注解还具备一些特性
- 注解方法可以有默认值
- 注解本身能够包含元注解 , 元注解是可以被用来注解其他注解的
( 上述的Documented , Target , Inherited , Retention就是元注解 , 仅此4种 )
这里需要提一下的是 java.lang.annotation.Annotation 接口
它是所有注解类型都需要扩展的公共接口 , 但手工扩展该接口并不能定义注解
一个注解本身也相当于一个接口
其对象是一个代理类的对象 , 将在下面的反射解析注解中看到
注解使用
public class Test { @Override @InfoMethod(author= "22",comments="Main method",date="2016-02-04") //存在默认值的注解方法,使用时可以不传值,其余都要传值 public String toString(){ return "Overriden toString method" ; } @Deprecated @InfoMethod(author= "33",comments="Deprecated method",date="2016-02-16") public static void oldMethod (){ System. out.println("该方法已过时" ); } @SuppressWarnings({ "unchecked", "rawtypes" }) @InfoMethod(comments= "SuppressWarnings method",date="2016-02-16") public static void genericsTest(){ List list = new ArrayList(); list.add( "OK"); oldMethod(); } }
注解的解析
使用Java的反射机制来解析类当中的注解
@Retention必须被设置为 RUNTIME , 否则注解信息在执行过程中将不可用
所以也就不能从中得到任何与注解有关的数据
public static void main(String[] args) throws Exception{ Class<Test> cls = (Class<Test>) Test. class; for(Method method : cls.getDeclaredMethods()){ //获取到该类中的所有方法(不包括继承的)并执行遍历 if(method.isAnnotationPresent(InfoMethod.class)){ //如果指定类型的注解存在于此元素上 for(Annotation anno : method.getAnnotations()){ System.out.println(method.getName()+"方法上的注解有" +anno); } InfoMethod methodAnno = method.getAnnotation(InfoMethod.class); //获取到该方法上的InfoMethod注解对象 System.out.println("--author:" +methodAnno.author()); System.out.println("--date:" +methodAnno.date()); System.out.println("--comments:" +methodAnno.comments()); } } }
执行结果如下
可以发现除了我们自定义的注解@InfoMethod之外
只有@Deprecated被获取到了
分别去找 @Override和@SuppressWarnings 的源代码可以发现
他们的保留时间都不是 RUNTIME
- SOURCE - 注解仅存在于源码中
- CLASS - 注解会在class字节码文件中存在 , 但运行时无法获得
- RUNTIME - 注解会在class字节码文件中存在 , 运行时可以通过反射获得
补充说明 :
getAnnotations 方法在Field Method Class 类当中都存在
可以获取添加在属性 方法 类之上的注解