自定义注解

来源:互联网 发布:jre 8u91 windows x32 编辑:程序博客网 时间:2024/04/27 23:51

一、元注解
放在被定义的一个注解类的前面,是对注解的一种限制。
@Retention:用来说明该注解类的生命周期。可选参数:
RetentionPolicy.SOURCE:注解只保留在源文件中
RetentionPolicy.CLASS:注解保留在class文件中,在加载到JVM虚拟机时丢弃
RetentionPolicy.RUNTIME:注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解

@Target:用于描述注解的使用范围。可选参数:
ElementType.TYPE:说明该注解只能被声明在一个类前。
ElementType.FIELD:说明该注解只能被声明在一个类的字段前。
ElementType.METHOD:说明该注解只能被声明在一个类的方法前。
ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前。
ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前。
ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前。
ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。
ElementType.PACKAGE:说明该注解只能声明在一个包名前。

@Documented:
   @Documented是一个标记注解,没有成员。@Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中。

@Inherited:

   @Inherited 元注解是一个标记注解,@Inherited表示这个注解可以继承超类注解。即子类可以获取父类的注解信息。

 注意:该注解只能用来声明类。不能用于接口

二、自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

定义注解格式:
  public @interface 注解名 {定义体}

注解参数设定:

(1)注解类型的参数设定只能用public或默认(default)这两个访问修饰。

(2)参数支持数据类型

      1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
  2.String类型
  3.Class类型
  4.enum类型
  5.Annotation类型
  6.以上所有类型的数组

注解参数默认值:

注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。

三、读取注解

Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类:

  Class:类定义
  Constructor:构造器定义
  Field:类的成员变量定义
  Method:类的方法定义
  Package:类的包定义

  java.lang.reflect 包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射API扩充了读取运行时Annotation信息的能力。当一个Annotation类型被定义为运行时的Annotation后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。
  AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:

  方法1:<T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。
  方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
  方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
  方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注解。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

四、示例

示例一:

定义注解:

package com.learn.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface InformationAnnotation {String school() default "CPU";public String city() default "江苏";}

使用类:

package com.learn.annotation;@InformationAnnotation(school="NJAU")public class Student {}
调用类:

package com.learn.annotation;public class Test {public static void main(String[] args) {InformationAnnotation information = Student.class.getAnnotation(InformationAnnotation.class);//输出赋予的值System.out.println(information.school());//输出默认值System.out.println(information.city());}}
结果:

NJAU江苏

示例二:子类继承了父类的注解,获取到父类的注解参数值

定义注解

package com.learn.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inheritedpublic @interface InformationAnnotation {public String school() default "CPU";public String city() default "江苏";}
使用父类:

package com.learn.annotation;@InformationAnnotation(city="上海")public class Parent {public void doSomething(){System.out.println("do some thing");}}
子类:

package com.learn.annotation;public class Son extends Parent{}
测试类:

package com.learn.annotation;public class Test {public static void main(String[] args) {InformationAnnotation information = Son.class.getAnnotation(InformationAnnotation.class);//输出赋予的值System.out.println(information.school());//输出默认值System.out.println(information.city());}}
结果:
CPU上海












0 0