Java编程之Annotation全解析

来源:互联网 发布:淘宝售后申请时间限制 编辑:程序博客网 时间:2024/06/15 03:12

前言

通过本篇的学习可以达到以下目标:
了解Annotation的作用
掌握JDK 1.5中内建的3种Annotation
掌握自定义Annotation的语法及其应用
掌握@Retention,@Target,@Documented,@Inherited注释。

Annotation简介

J2SE5.0提供了很多新的特性。其中一个很重要的特性就是对元数据(Metadata)的支持。在J2SE5.0中,这种元数据称为注释(Annotation).通过使用注释,程序开发人员可以在不改变原有逻辑的情况下,在源文件嵌入一些补充的信息。

Annotation可以用来修饰类,属性,方法,而且Annotation不影响程序运行,无论是否使用Annotation代码都可以正常执行。

java.lang.annotation.Annotation是Annotation的接口,只要是Annotation都必须实现此接口。

此接口定义如下:

public interface Annotation{public Class<? extends Annotation> annotationType();//返回此Annotation的注释类型public boolean equals(Object obj);public int hashCode();String toString();

本篇以后所介绍的系统内建的Annotation和用户自定义的Annotation都是默认实现了此接口。
这里写代码片ext/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlqaXpoaTE5OTUwMTIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast” alt=”这里写图片描述” title=”” />
这里写图片描述

@Override

@Override主要是在方法覆写时使用,用于保证方法覆写的正确性。下面介绍此注释的基本使用。
代码如下:

package org.;jz.systemannotation;class Person{   //定义Person类public String getInfo(){  //定义getInfo()方法 return "这是一个Person类。"  //返回信息 }}class Student extends Person{  //子类继承父类@Overridepublic String getInfo(){  //覆写父类方法return "这是一个Student类"; }}public class OverrideAnnotationDemo01{public static void main(String[] args){ Person per=new Student();  //通过子类实例化父类对象 System.out.println(per.getInfo()); //输出信息 }}   

程序运行结果:

这是一个Student类

以上的程序中的子类Student继承Person类,之后覆写了Person类中的getInfo()方法,程序的运行结果与之前一样,唯一不同的只是在覆写的getInfo()方法前加上了@Override注释,这样做的目的主要是防止用户在覆写方法时将方法定义出错

注意

@Override在使用时只能在方法上应用,而其他元素,如类,属性等上是不能使用此Annotation的。

@Deprecated

@Deprecated注释的主要功能是用来声明一个不建议使用的方法的方法。如果在程序中使用了此方法,则在编译时就出现警告信息。

使用@Deprecated声明一个不建议使用的方法

package org.demo.systemannotation;class Demo{  //定义一个Demo类@Deprecated  //声明不建议使用的操作public String getInfo(){ //此方法不建议使用return "这是一个Person类"   //返回信息  }}public class DeprecatedAnnotationDemo01{public static void main(String[] args){Demo d=new Demo();  //实例化Demo对象System.out.println(d.getInfo()); //编译时,将出现警告信息  }}     

以上的类在getInfo()方法上使用了@Deprecated注释声明,这就表示此方法不建议继续使用,所以在编译时出现了警告。另外与@Override有所区别的是,@Deprecated除了可以在方法上声明外,在类中也可以进行声明。

@SuppressWarnings

@SuppressWarnings注释的主要功能是用来压制警告,例如,之前讲泛型操作时,如果在一个类声明时没有指明泛型,则肯定在编译时产生警告,那么此时就可以使用@SuppressWarnings压制住这种警告。

如下面代码所示:

package org.ljz.systemannotation;@Deprecated   //以下操作不建议使用class Demo<T>{   //定义了Demo类,使用泛型      private T var;  //定义泛型变量      public T getVar(){  //取得泛型变量的内容      return var;}public void setVar(T var){    //设置泛型变量this.var=var;  }}public class SuppressWarningAnnotationDemo02{@SuppressWarnings({"unchecked","deprecation"}) //此时压制两条警告public static void main(String[] args){ Demo d=new Demo   //编译时的警告信息将被压制d.setVar("ljz");System.out.println(" 内容: "+d.getVar());   //输出   }}        

以上程序同时存在了泛型和不建议使用方法两种警告,但是由于使用了@SuppressWarning注释,所以此时在程序编译时将不会出现任何的警告信息。

以上在压制多个警告时,使用了unchecked和deprecation两种关键字,是以字符串数组的形式设置进行声明的。@SuppressWarnings中的可以压制的警告类型如下表所示:
这里写图片描述

自定义Annotation

之前已经介绍了3种Java中自建的Annotation,只要通过固定的格式调用即可。接下来我将介绍如何自定义Annotation.

Annotation常用格式

[public] @interface Annotation 名称{
数据类型 变量名称();

要定义Annotation必须使用@interface的方式进行定义

自定义一个Annotation

package org.ljz.defaultannotation;public @interface MyDefaultAnnotationNoneParam{ //定义Annotation}

使用Annotation

package org.ljz.defaultannotation;@MyDefaultAnnotationNoneParam  //使用自定义的Annotationclass Demo{}

以上的Demo类的声明处就使用了之前定义好的MyDefaultAnnotationNoneParam注释

向Annotation中设置内容

package org.ljz.defaultannotation;public @interface MyDefaultAnnotationArrayParam{ //定义Annotationpublic  String[] value(0; //接收设置的内容是一个字符串数组} 

调用Annotation并设置数组属性

package org.ljz.defaultannotation;@MyDefaultAnnotationArrayParam{value={"name","ljz"})//使用自定义的Annotationclass Demo{}

在以上操作中,所有的内容都是需要用户在调用Annotation时手工设置的。

Retention和RetentionPolicy

在Annotation中,可以使用Retention定义一个Annotation的保存范围。此Annotation的定义如下:

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Retention{
RetentionPolicy value();
}

在以上的Retention定义中存在一个RetentionPolicy的变量,此变量用于指定Annotation的保存范围。
这里写图片描述

定义在RUNTIME范围有效的Annotation

package org.ljz.retentiondemo;import java.lang.annotion.Retention;import java.lang.annotation.RetentionPolicy;@Retention(value=RetentionPolicy.RUNTIME) //此Annotation在执行时起作用public @interface MyDefaultRetentionAnnotation{public String name() default"ljz"; //只能设置枚举中的取值}

以上定义的Annotion在程序执行时起作用,这是一种比较常见的使用方式,而如果此时将其设置成其他范围,则以后在Annotation的应用中肯定是无法访问到的,要想让Annotion起作用,则必须结合JAVA中的反射机制。

通过反射取得Annotation

这里写图片描述

范例——取得全部Annotion

为了方便操作,以下程序首先定义了一个类,并在类中的方法上使用了系统内建好的3个Annotation。

定义一个简单类

package org.ljz.reflectannotion;public class SimpleBeanOne{@SuppressWarnings("unchecked") //使用@@SuppressWarnings的Annotation@Deprecated  //使用@Deprecated的Annotation@Override    //使用@Override的Annotationpublic String toString(){ //覆写toStringreturn "Hello ljz""  //返回信息 }}   

以上程序覆写的toString()方法中使用了3个内建的Annotation,要想取得SimpleBeanOne中toString()方法的全部Annotation,则必须首先通过反射找到toString()方法。

取得全部Annotation

package org.ljz.reflectannotation;import java.lang.reflect.Method;public class ReflectDemo01{public static void main(String args[])throws Exception{//所有异常抛出Class<?> c=null;  //取得Class实例c=Class.forName("org.ljz.reflectannotion.SimpleBeanOne")Method toM=c.getMethod("toString");//取得toString()方法Annotation an[]=toM.getAnnotation();//取得全部的Annotationfor(Annotation a: an){  //foreach输出System.out.println(a);  //直接输出信息       }     } }      

程序运行结果:

@java.lang.Deprecated()

SimpleBeanOne的toString()方法上虽然使用了3个Annotation注释,但是最后真正的得到的只能是一个,这是因为只有Deprecated使用了RUNTIME的方式声明,所以只有它可以取得。

阅读全文
0 0