Annotation的学习

一、概念:     
     Annotation它提供了一种安全的类似注释的机制,用来将任何的信息或元数据( metadata)与程序元素(类、方法、成员变量等)进行关联。更通俗的意思是为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且是供指定的工具或框架使用的。A nnontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。

二、原理:
     Annotation其实是一种接口。通过 Java的反射机制相关的 API来访问 annotation信息。 相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。 annotation是不会影响程序代码的执行,无论 annotation怎么变化,代码都始终如一地执行。 annotation是不会影响程序代码的执行,无论 annotation怎么变化,代码都始终如一地执行。
     Annotationinterface的异同
1)、 Annotation类型使用关键字 @interface而不是 interface
2)、 Annotation类型、方法定义是独特的、受限制的。
      Annotation 类型的方法必须声明为 无参数、无异常抛出的。这些方法定义了 annotation的成员:方法名成为了成员名,而方法返回值成为了成员的类型。而方法返回值类型必须为 primitive类型、 Class类型、枚举类型、 annotation类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用  default和一个默认数值来声明成员的默认值, null不能作为成员默认值,这与我们在非 annotation类型中定义方法有很大不同。
      Annotation类型和它的方法不能使用 annotation类型的参数、成员不能是 generic。只有返回值类型是 Class的方法可以在 annotation类型中使用 generic,因为此方法能够用类转换将各种类型转换为 Class
3)、 Annotation类型又与接口有着近似之处。
     它们可以定义常量、静态成员类型(比如枚举类型定义)。 Annotation类型也可以如接口一般被实现或者继承。

三、应用场合
      annotation一般作为一种辅助途径,应用在软件框架或工具中,在这些工具类中根据不同的  annontation注解信息采取不同的处理过程或改变相应程序元素(类、方法及成员变量等)的行为。
     例如: JunitStrutsSpring等流行工具框架中均广泛使用了 annontion。使代码的灵活性大提高。

四、基本语法:
Java目前包括三种标准注解和四种元注解。元注解主要负责注解其他注解的。
三种标准注解:

@Override,表示当前的方法定义覆盖了父类中的方法。必须要有相同的方法签名即(方法名,参数类型,参数顺序,参数个数)都一样。否则在编译过程中发出错误提示。

@Deprecated,对不应该再使用的方法添加注解,当使用这个方法的时候,会在编译时候显示提示信息。

@SuppressWarnings,关闭不当的编译器报警信息

四种元注解:

 @Target,表示该注解可以用什么地方。

TYPE : 类、接口或enum声明

FIELD: 域(属性)声明

METHOD: 方法声明

PARAMETER: 参数声明

CONSTRUCTOR: 构造方法声明

LOCAL_VARIABLE:局部变量声明

ANNOTATION_TYPE:注释类型声明

PACKAGE: 包声明

 @Retention,表示需要在什么级别保存该注解信息。

1. SOURCE//按照规定使用注释,但是并不将它保留到编译后的类文件中
2. CLASS//将注释保留在编译后的类文件中,但是在运行时忽略它 
3. RUNTIME//将注释保留在编译后的类文件中,并在第一次加载类时读取它  

 @Documented,将此注解包含到Javadoc中。

 @Inherited,允许子类继承父类的注解。


五、自定义Annocation
     先看一个简单的annocation
package  com.cts.elt.annotation;

import  java.lang.annotation.Documented;
import  java.lang.annotation.Retention;
import  java.lang.annotation.ElementType;
import  java.lang.annotation.RetentionPolicy;
import  java.lang.annotation.Target;

@Target (ElementType. TYPE  ) //此注解用在类上面
@Retention (RetentionPolicy. RUNTIME ) //将注释保留在编译后的类文件中,并在第一次加载类时读取它 
@Documented

public  @interface  MyAnnotation1  {

        String value();

}

 上面这个MyAnnotation1.class文件包含一个值,下面来一个含有两个值的annotation:
package  com.cts.elt.annotation;

import  java.lang.annotation.Documented;
import  java.lang.annotation.ElementType;
import  java.lang.annotation.Retention;
import  java.lang.annotation.RetentionPolicy;
import  java.lang.annotation.Target;

@Target (ElementType. METHOD  )
@Retention (RetentionPolicy. RUNTIME )
@Documented
public  @interface  MyAnnotation2  {

        String description();

         boolean  isAnnotation();

}

  关键是来看这两个自定义annotation的用法:
package  com.cts.elt.annotation;

@MyAnnotation1  ( "this isannotation1"  )
public  class  AnnotationDemo {

      @MyAnnotation2 (description =  "this is annotation2" , isAnnotation =  true )
      public  void  sayHello() {

          System.  out .println(  "hello world!" );

     }

}

 如果把@MyAnnotation1与@MyAnnotation2的位置换一换,会怎么样?(肯定报错啦!)

六、自定义Annocation高级篇
情景设计:设有一CLASS叫Student,其中有三个fields: 

private String name = "";

private int age = 0;

private String studentId = "";


 相应的每一个field有一对的set, get方法。 然后我在每个set方法上造一个annotation叫ValueBind的注解,其作用是: 只要set方法上带有ValueBind注解,它就会根据这个字段的类型把一个默认值,自动赋给Student类中相对应的field。
      1、先来看一下Student类: 
package  com.cts.elt.annotation;

import  java.io.Serializable;
import  com.cts.elt.annotation.ValueBind.fieldType;

public  class  Student  implements  Serializable {
     
      private  String name =  "" ;

      public  String getName() {
            return  name;
     }

      @ ValueBind(type = fieldType.STRING, value = "aa")
      public  void  setName(String name) {
            this .name = name;
     }

      public  int  getAge() {
            return  age;
     }

      @ ValueBind(type = fieldType.INT, value = "30")
      public  void  setAge(  int  age) {

            this .age = age;

     }

      public  String getStudentId() {

            return  studentId;

     }

      @ ValueBind(type = fieldType.STRING, value = "101")
      public  void  setStudentId(String studentId) {

            this .studentId = studentId;

     }

      private  int  age = 0;

      private  String studentId =  "" ;

}

      2、自定义一个ValueBind的Annocation:
package  com.cts.elt.annotation;

import  java.lang.annotation.Documented;
import  java.lang.annotation.ElementType;
import  java.lang.annotation.Retention;
import  java.lang.annotation.RetentionPolicy;
import  java.lang.annotation.Target;

@Target (ElementType. METHOD  )
@Retention (RetentionPolicy. RUNTIME )
@Documented
public  @interface  ValueBind  {

      enum  fieldType {
            STRING ,  INT
     };

     fieldType type();

     String value();

}

首先这个annotation只能被标注在方法上;其次它含有两个值,一个是enum类型,一个是String类型
     3、利用Java类反射机制来实现我们的Annocation:
package  com.cts.elt.annotation;

import  java.lang.reflect.*;

public  class  PersistStudent {

      public  static  void  main(String[] args)  throws  Exception {

          Object c = Class.forName( "com.cts.elt.annotation.Student" ).newInstance();

            try  {

              Method[] methodArray = c.getClass().getDeclaredMethods();

                for  (  int  i = 0; i < methodArray.  length ; i++) {

                     if  (methodArray[i].isAnnotationPresent(  ValueBind .  class )) { //如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
                        
                          ValueBind  annotation = methodArray[i].getAnnotation( ValueBind  . class ); //如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。

                        String type = String.valueOf(annotation.type());

                        String value = annotation.value();

                          if  (type.equals(  "INT" )) {

                              methodArray[i].invoke(c,  new  Integer[] {  new  Integer(value) });

                        }  else  {

                              methodArray[i].invoke(c,  new  String[] { value });

                        }

                   }

              }

              Student annotaedStudent = (Student) c;

              System.  out .println(  "studentId===="  + annotaedStudent.getStudentId()

              +  "  studentnName===="  + annotaedStudent.getName()

              +  "   student Age===="  + annotaedStudent.getAge());

          }  catch  (Exception e) {

                throw  new  Exception(e);

          }

     }

}

运行结果显示:
studentId====101  studentnName====aa   studentAge====30


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值