Java中注解的应用

来源:互联网 发布:微信小动画制作软件 编辑:程序博客网 时间:2024/06/07 23:03

Java中注解的应用

标签(空格分隔): Java


了解和入门注解的应用

  注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
  若一个方法已经过时,eclipse会给出”方法已经过时”的提示,可以在方法前加上注解:@SuppressWarnings("deprecation"),就不会对过时方法给出警告。

public class AnnotationTest {    @SuppressWarnings("deprecation")    public static void main(String[] args) {        // TODO Auto-generated method stub        System.runFinalizersOnExit(true);    }}

  如果一个方法过时,通常为了兼容性,我们不能直接把这个方法删除,但建议开发者使用其他的方法。

@Deprecatedpublic void sayHello(){    System.out.println("hello,world");}

  注意:在覆盖父类方法的使用,确保有@Override标记

注解的定义与反射调用

  定义一个最简单的注解:

public @interface MyAnnotation {}

  把它加在某个类上:

@MyAnnotationpublic class AnnotationTest {    public static void main(String[] args) {        // TODO Auto-generated method stub        if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){            MyAnnotation annotation = (MyAnnotation) AnnotationTest.class.getAnnotation(MyAnnotation.class);            System.out.println(annotation);        }    }}

  用反射进行测试AnnotationTest的定义上是否有@MyAnnotation,但结果是没有打印出任何结果,说明此时类上并没有标注注解。加上元注解@Retention(RetentionPolicy.RUNTIME),能够打印出结果:@com.qianming.MyAnnotation()
  根据反射测试的问题,引出@Retention元注解的讲解,其三种取值:

  • RetetionPolicy.SOURCE
  • RetetionPolicy.CLASS
  • RetetionPolicy.RUNTIME – 注解保持到程序运行时

  分别对应:java源文件–>class文件–>内存中的字节码。
  Java源文件转换为class文件的时候,有可能去掉注解;类加载器把class文件加载到内存的过程中,也有可能会去掉注解
  默认的值是class阶段
  对以上案例进行分析,在没加上元注解@Retention(RetentionPolicy.RUNTIME)的时候,上述代码加载到内存过程中,注解被去掉,导致最终无法打印出注解。
思考
  @Override,@SuppressWarnings,@Deprecatedz这三个注解的属性分别是是什么?
  1. @Override是给Java编译器看的,用完之后没有价值,所以注释保留到源代码阶段,属性应是RetetionPolicy.SOURCE
  2. 同理@SuppressWarnings也是给编译器看的,保留到源代码阶段,属性应该是RetetionPolicy.SOURCE
  3. 编译器在源程序上不能发现这个方法是否过时,编译器只有在类的字节码上才能知道。类加载器把class文件加载进入内存,检查字节码上是否有这个方法,所以它的属性是RetetionPolicy.RUNTIME

演示和讲解@Target元注解
  Target的默认值为任何元素,设置Target等于ElementType.METHOD,表示这个注释只能放在方法上,因此原来加在类上的注解就报错了。若改为用数组方式设置@Target({ElementType.METHOD,ElementType.TYPE})
,表示这个注解能够同时放在方法上,也能放在类型上
为什么不是class,而是TYPE?
  class实现一个接口TYPE,interface、class、Enum都是Java中的TYPE.  
  
  元注解以及其枚举属性值不用记,只要会看jdk提供那几个基本注解的API帮助文档的定义,并结合eclipse的提示功能。

为注解增加属性

定义基本类型的属性和应用属性

  在注解类中增加一个属性,但这个属性与方法类似,案例中添加一个color属性,写法:

@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {    String color();}

  在注解上加上color属性,并取得该属性的值:
  用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法
MyAnnotation a = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(a.color());

@MyAnnotation(color="red")public class AnnotationTest {    public static void main(String[] args) {        // TODO Auto-generated method stub        if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){            MyAnnotation annotation = (MyAnnotation) AnnotationTest.class.getAnnotation(MyAnnotation.class);            System.out.println(annotation.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

MetaAnnotation annotationAttr() default @MetaAnnotation("xxxx");@MyAnnotation(annotationAttr=@MetaAnnotation(“yyy”) )

  可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象,同样的道理,可以认为上面这个@MetaAnnotation是MetaAnnotation类的一个实例对象,调用代码如下:

MetaAnnotation ma =  myAnnotation.annotationAttr();System.out.println(ma.value());

  注解的详细语法可以通过看java语言规范了解。

0 0