Java编程之Annotation全解析
2017-10-02 17:24
387 查看
前言
通过本篇的学习可以达到以下目标:了解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{ //子类继承父类 @Override public 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 //使用自定义的Annotation class Demo{ }
以上的Demo类的声明处就使用了之前定义好的MyDefaultAnnotationNoneParam注释
向Annotation中设置内容
package org.ljz.defaultannotation; public @interface MyDefaultAnnotationArrayParam{ //定义Annotation public String[] value(0; //接收设置的内容是一个字符串数组 }
调用Annotation并设置数组属性
package org.ljz.defaultannotation; @MyDefaultAnnotationArrayParam{value={"name","ljz"})//使用自定义的Annotation class 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的Annotation public String toString(){ //覆写toString return "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();//取得全部的Annotation for(Annotation a: an){ //foreach输出 System.out.println(a); //直接输出信息 } } }
程序运行结果:
@java.lang.Deprecated()
SimpleBeanOne的toString()方法上虽然使用了3个Annotation注释,但是最后真正的得到的只能是一个,这是因为只有Deprecated使用了RUNTIME的方式声明,所以只有它可以取得。
相关文章推荐
- Java并发编程:volatile关键字解析
- Java并发编程:volatile关键字解析
- 编程用 JAVA 解析 XML 的方式。
- 【Java并发编程】volatile关键字解析
- Java并发编程:volatile关键字解析
- 开源项目源码解析-Java 注解 Annotation
- Java Annotation之应用篇 – 运行期动态解析annotation
- Java中的Annotation解析(一)
- 解析Java类和对象的初始化过程_J2EE_Java开发_软件开发-编程-IT资源网
- Java笔记二十.深入解析I/O编程之文件访问类
- 解析Java体系结构对信息安全的支持-Java基础-Java-编程开发
- 详细解析抽象类和接口的区别-Java基础-Java-编程开发
- java网络编程四:InetAddress类、URL类、URLConnection类解析及用法示例
- Java并发编程:volatile关键字解析
- Java并发编程:Callable、Future和FutureTask原理解析
- Android的数据处理:使用annotation实现JSON字符串解析为java对象
- java事务全解析(七)--像Spring一样使用Transactional注解(Annotation)
- Java并发编程:volatile关键字解析(转载)
- Java并发编程:volatile关键字解析
- java annotation processing tools(APT)实例解析