`
chenzehe
  • 浏览: 532659 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java 注解 Anonotation

阅读更多

1、 什么是注解

Annotation表示一种注释的语法,在 Java 中最早提倡的是程序与配置相分离,而最新的理论是把所有配置直接写入到代码中,如果想完成这样的功能,则使用 Annotation

 

2、 系统内建的Annotation

 

2.1  @Override

重写父类的方法

 

2.2  @Deprecated

表示不建议使用的操作,如果使用该操作也不报错,只是在编辑器中出现横线警告信息,不建议使用。如Date 对像中的很多方法。

@ Deprecated

public   int  getDay ()   {

     return  normalize () .getDayOfWeek ()  - gcal.SUNDAY;

}

 

2.3   @SuppressWaring表示压制警告,如果出现警告信息,则可以压制不提示。 @SuppressWaring 的属性 String[] value() 为数组,说明可以同时压制多个警告。

@ Target ({ TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE })

@ Retention ( RetentionPolicy.SOURCE )

public   @interface  SuppressWarnings  {

     String []  value () ;

}

 

3、自定义 Annotation

 

3.1 语法

public @interface 名称 {

}


3.2 定义 MyAnnotaion

package  com.chenzehe.annotation;

    public   @interface   MyAnnotation   {

}

如果要使用此Annotation, 则使用 @ 符访问,不在同一个包中需要导入。如下面 Info 类的使用:

package com.chenzehe.annotation;

@MyAnnotation

public class Info {

}


3.3 Annotation的属性定义

Annotation的属性定义以 () 结尾。

package  com.chenzehe.annotation;

public   @interface   MyAnnotation   {

     public  String key () ;

     public  String value () ;

}

上面Annotation 定义了两个变量 key value ,如果要使用此 Annotation ,则必须明确的给出其内容。如:

package  com.chenzehe.annotation;

@MyAnnotation ( key= "name" ,value= "chenzehe" )

public   class  Info  {

}

 

如果想给Annotation 的变量设置默认值,则使用 default 关键字完成,如:

package  com.chenzehe.annotation;

public   @interface   MyAnnotation   {

  public  String key ()   default   "name" ;

    public  String value ()   default   "chenzehe" ;

}

使用此Annotation 时,可以不用显示的设置变量值,而使用默认值。


3.4 Annotation中的属性值可以通过枚举限制

定义枚举类型Color:

package  com.chenzehe.annotation;

public   enum  Color  {

     RED , GLREN , BLUE ;

}

MyAnnotation 中定义一个 Color 类型的变量:

package  com.chenzehe.annotation;

public   @interface   MyAnnotation   {

     public  Color color ()   default  Color. RED ;

}

则使用MyAnnotation 中的 color 变量时,值只能取 Color 中定义的类型:

package  com.chenzehe.annotation;

@MyAnnotation ( color= "red" )

public   class  Info  {

}

上面给变量color 赋值出错,正确如下:

package  com.chenzehe.annotation;

@MyAnnotation ( color = Color. RED )

public   class  Info  {

}


3.5 Annotation中的属性为数组类型

如果Annotation 中的属性为数组类型,则使用的时候必须按照数组的方式操作。

package  com.chenzehe.annotation;

public   @interface   MyAnnotation   {

public  String []  urls () ;

}

使用:

package  com.chenzehe.annotation;

@MyAnnotation ( urls =  {   "www.baidu.com" "g.cn"   })

public   class  Info  {

}

4 注释类型 Retention 枚举 RetentionPolicy

@Documented

@Retention ( value = RUNTIME )

@Target ( value = ANNOTATION_TYPE )

public @interface  Retention

      指示注 类型的注释要保留多久 ,也就是作用范围。 如果注释类型声明中不存在 Retention  注释,则保留策略默认为  RetentionPolicy.CLASS 。只有元注释类型直接用于注释时, Target  元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。

枚举 RetentionPolicy 定义了三种 Annotation的范围:

CLASS   在编译之后的 class文件中作用

RUNTIME   在运行的时候起作用

SOURCE   只在源代码中起作用

系统内置的三个Annotation 的作用域分别为:

@ Override @Retention ( value = SOURCE ) 源码

@ Deprecated @Retention ( value = RUNTIME ) 运行时

@ SuppressWarnings @Retention ( value = SOURCE ) 源码

 

5、 反射与Annotation

一个Annotation 如果要想起作用,则肯定要依赖反射机制,通过反射可以取得一个方法上声明的  Annotation 全部内容。任何一下自定义的 Annotation 都是继承了 java.lang.annotation.Annotation 接口。

Field   Method   Constructor  的父类 AccessibleObject   定义了如下与Annotation 操作相关的方法:

取得全部Annotation  public  Annotation []   getAnnotations ()   

判断操作的是否是指定的Annotation public boolean  isAnnotationPresent ( Class <? extends  Annotation > annotationClass) 

例:下面Info 类中 toString() 方法使用的 Annotation ,在 Test 类中用反射访问这些 Annotation

package  com.chenzehe.annotation;

public   class  Info  {

     @Override

     @Deprecated

     @SuppressWarnings ( value =  "" )

     public  String  toString ()   {

         return   "Hello World!" ;

     }

}

 

package  com.chenzehe.annotation;

import  java.lang.annotation.Annotation;

import  java.lang.reflect.Method;

public   class  Test  {

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

         Class<?> cls = Class. forName ( "com.chenzehe.annotation.Info" ) ;

         Method method = cls.getMethod ( "toString" ) ;

         Annotation []  annotations = method.getAnnotations () ;

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

             System. out .println ( annotations [ i ]) ;

         }

     }

}

输出:@java.lang.Deprecated() ,而 Info 类中使用的三个 Annotation 中,只有 Deprecated 的范围为 runtime ,说明只有范围在 runtime 的才能被找到。

 

MyAnnotation 类改成 runtime 范围,并在 Test 类中用反射取得他的属性:

package  com.chenzehe.annotation;

import  java.lang.annotation.Retention;

import  java.lang.annotation.RetentionPolicy;

@Retention ( value = RetentionPolicy. RUNTIME )

public   @interface   MyAnnotation   {

     public  String key ()   default   "name" ;

     public  String value () ;

}

Info中使用该 Annotation

package  com.chenzehe.annotation;

public   class  Info  {

     @Override

     @Deprecated

     @SuppressWarnings ( value =  "" )

     @MyAnnotation ( value= "chenzehe" )

     public   String   toString ()   {

         return   "Hello World!" ;

     }

}

Test类中使用反射取得其属性:

package  com.chenzehe.annotation;

import  java.lang.annotation.Annotation;

import  java.lang.reflect.Method;

public   class  Test  {

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

         Class<?> cls = Class. forName ( "com.chenzehe.annotation.Info" ) ;

         Method method = cls.getMethod ( "toString" ) ;

         Annotation []  annotations = method.getAnnotations () ;

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

             if   ( method.isAnnotationPresent ( MyAnnotation . class ))   {

                 MyAnnotation  myAnnotation = method.getAnnotation ( MyAnnotation . class ) ;

                 String key = myAnnotation.key () ;

                 String value = myAnnotation.value () ;

                 System. out .println ( key +  ":"  + value ) ;

             }

         }

     }

}

 

6、 Target

java.lang.annotation 中已定义的注解类型 Target  ,用于指定所定义的注解使用的范围为方法、类、属性等。

默认情况下一个自定义的Annotation 可以在任意地方使用,如自定义的 MyAnnotation ,如果没有指定 Target ,则可以在任意地方使用:

package  com.chenzehe.annotation;

@MyAnnotation ()

public   class  Info  {

     @MyAnnotation ()

     private  String name ;

     @MyAnnotation ()

     public  String toString ()   {

         return   "Hello World!" ;

     }

}

Target 的定义中, value 的属性类型为   ElementType [] ,所指定的范围有以下八种:

1、 只能在Annotation 中出现: ANNOTATION_TYPE  

2、 只能在构造方法中出现: CONSTRUCTOR  

3、 在属性中出现: FIELD  

4、 只能在本地变量中出现: LOCAL_VARIABLE  

5、 在方法上出现: METHOD  

6、 在包声明中出现: PACKAGE  

7、 在参数声明中出现: PARAMETER  

8、 类、接口(包括注释类型)或枚举声明 中使用:   TYPE  

如以下自定义的MyAnnotation 只能在方法中使用:

package  com.chenzehe.annotation;

import  java.lang.annotation.ElementType;

import  java.lang.annotation.Retention;

import  java.lang.annotation.RetentionPolicy;

import  java.lang.annotation.Target;

@Retention ( value = RetentionPolicy. RUNTIME )

@Target ( value= ( ElementType. METHOD ))

public   @interface   MyAnnotation   {

    public  String key ()   default   "name" ;

    public  String value ()   default   "chenzehe" ;

}

Target中的属性 value 定义为数组类型,所以可以同时设置多个 ElementType ,如:

@Target ( value =  {  ElementType. METHOD , ElementType. FIELD   })

 

7、 Document注解

java.lang.annotation 中定义的注解类型 Documented  , 指示某一类型的注释将通过 javadoc  和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用  Documented  来注释的,则其注释将成为注释元素的公共  API  的一部分。 

如声明 MyAnnotation注解:

package  com.chenzehe.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;

@Documented

@Retention ( value = RetentionPolicy. RUNTIME )

@Target ( value =  {  ElementType. METHOD , ElementType. FIELD   })

public   @interface   MyAnnotation   {

     public  String key ()   default   "name" ;

     public  String value ()   default   "chenzehe" ;

}

Info 类中使用:

package  com.chenzehe.annotation;

public   class  Info  {

     /**

     * 此方法是覆盖Object中的toString()方法

     */

     @ MyAnnotation ()

     public  String toString ()   {

         return   "Hello World!" ;

     }

}

可以通过eclipse export 导出 javadoc ,在其注释中能看到上面编写的注释

 

8、 Inherited

java.lang.annotation 中声明 Inherited  ,表示该annotation 是否被该子类断承下去,如果没有此注解,说明不能被断承。

如自定义的MyAnnotation ,加入 @Inherited ,说明此 Annotation 可以被子类断承:

package  com.chenzehe.annotation;

import  java.lang.annotation.Inherited;

import  java.lang.annotation.Retention;

import  java.lang.annotation.RetentionPolicy;

@Inherited

@Retention ( value = RetentionPolicy. RUNTIME )

public   @interface   MyAnnotation   {

    public  String key ()   default   "name" ;

     public  String value ()   default   "chenzehe" ;

}

Info类中使用该 Annotation

package  com.chenzehe.annotation;

@ MyAnnotation

public   class  Info  {

}

创建Info 类的子类 PersonInfo

package  com.chenzehe.annotation;

public   class  PersonInfo  extends  Info  {

}

使用反射取得PersonInfo 类的 annotation 信息:

package  com.chenzehe.annotation;

import  java.lang.annotation.Annotation;

public   class  Test  {

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

         Class<?> cls = Class. forName ( "com.chenzehe.annotation.PersonInfo" ) ;

         Annotation []  annotations = cls.getAnnotations () ;

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

             System. out .println ( annotations [ i ]) ;

         }

     }

}

如果MyAnnotation 中加入 @Inherited ,则可以取到 MyAnnotaion信息,如果没有加则取不到。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics