Java使用@interface定义注解

举报
yd_221104950 发表于 2020/12/03 00:05:21 2020/12/03
【摘要】 java用@interface定义注解。在程序中加上注解,JAVAC编译器和VM可以利用它来做一些相应的处理。 元注解 元注解是注解的注解。有如下这一些: @Retention @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @...

java用@interface定义注解。在程序中加上注解,JAVAC编译器和VM可以利用它来做一些相应的处理。

元注解

元注解是注解的注解。有如下这一些:

@Retention

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention { /** * Returns the retention policy. * @return the retention policy */ RetentionPolicy value();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

表明带注解类型的注解将会保留多久。如果一个注解类型的声明上没有Retention注解,那么它默认的保留策略是RetentionPolicy.CLASS。
Retention注解有一个属性value,它是用来指定保留策略的。这个属性的类型是RetentionPolicy,它的值有:

public enum RetentionPolicy { /** * Annotations are to be discarded by the compiler. */ SOURCE, /** * Annotations are to be recorded in the class file by the compiler * but need not be retained by the VM at run time.  This is the default * behavior. */ CLASS, /** * Annotations are to be recorded in the class file by the compiler and * retained by the VM at run time, so they may be read reflectively. * * @see java.lang.reflect.AnnotatedElement */ RUNTIME
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

(1)SOURCE:表示注解的信息会被编译器丢弃,不会保留在class文件中,注解的信息只会留在源文件中,所以这里注解信息一般都用在编译阶段。
(2) CLASS :表示注解的信息会被编译器记录在class文件中;但在运行时,不会被虚拟机保留着,所以它们不可以用反射的方式读取到;如果不指定Retention的值,默认就是CLASS;
(3)RUNTIME:表示注解的信息会被编译器保留在class文件里;在运行时,还会被虚拟机保留着,所以它们可以用反射的方式读取到,所以这里注解信息一般都用在程序运行阶段;
例子:

@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation1 {
}

@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation2 {
}

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation3 {
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

@Target

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target { /** * Returns an array of the kinds of elements an annotation type * can be applied to. * @return an array of the kinds of elements an annotation type * can be applied to */ ElementType[] value();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

表明注解类型适用的上下文。如果@Target元注解没有在注解类型上,那么这个注解可以作为一个修饰符用在任何声明上,除了类型参数声明。如有注解类型上有@Target元注解,那么编译器将根据ElementType枚举常量限制它的使用范围。@Target有一个属性ElementType[]类型的属性 value(),就是通过它来指定的。ElementType枚举常量有以下这些:

public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, /** Field declaration (includes enum constants) */ FIELD, /** Method declaration */ METHOD, /** Formal parameter declaration */ PARAMETER, /** Constructor declaration */ CONSTRUCTOR, /** Local variable declaration */ LOCAL_VARIABLE, /** Annotation type declaration */ ANNOTATION_TYPE, /** Package declaration */ PACKAGE, /** * Type parameter declaration * * @since 1.8 */ TYPE_PARAMETER, /** * Use of a type * * @since 1.8 */ TYPE_USE
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • TYPE: 类、接口(包括注解类型)、枚举声明
  • FIELD:字段声明(包括枚举常量)
  • METHOD:方法声明
  • PARAMETER:形式参数声明
  • CONSTRUCTOR:构造函数声明
  • LOCAL_VARIABLE:局部变量声明
  • ANNOTATION_TYPE:注释类型声明
  • PACKAGE:包声明
  • TYPE_PARAMETER:类型参数声明
  • TYPE_USE:类型的使用

这个@Target元注解表示声明的类型是仅用作复杂注解类型中的成员类型声明。它不能直接用于注释任何内容,如:

 @Target({})
 public @interface MemberType { ...
  }

  
 
  • 1
  • 2
  • 3
  • 4

综合例子

@Documented
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE})
public @interface NonNull {
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

我们常自定义用@Retention(RetentionPolicy.RUNTIME) 注释的注解,因为这样的注解会保留在VM中,这样我们才有办法通过反射技术来读取到注解,再做相应处理,事不宜迟,我们来自定义一个:

@Retention(RetentionPolicy.RUNTIME)  
public @interface MyAnnotation{ String city() default "Test"; String name(); int[] array() default { 2, 4, 5, 6 }; EnumTest.TrafficLamp lamp() ; TestAnnotation lannotation() default @TestAnnotation(value = "ddd"); Class style() default String.class;  
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

上面程序中,定义一个注解@MyAnnotation,定义了6个属性,他们的名字为:

city,name,array,lamp,lannotation,style.

属性city类型为String,默认值为gege  
属性name类型为String,没有默认值  
属性array类型为数组,默认值为2,4,5,6  
属性lamp类型为一个枚举,没有默认值  
属性lannotation类型为注解,默认值为@TestAnnotation,注解里的属性是注解  
属性style类型为Class,默认值为String类型的Class类型  

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

使用注解MyAnnotation:

@MyAnnotation( city= "beijing", name="zhijincheng",array={},lamp=TrafficLamp.RED,style=int.class)  
public class TestExample  
{ @MyAnnotation(lannotation=@TestAnnotation(value="baby"), name = "zhijincheng",array={1,2,3},lamp=TrafficLamp.YELLOW) @Deprecated @SuppressWarnings("") public void read() { System.out.println("output something!"); }  
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

通过反射读取注解的信息:

public class MyAnnotationReflection{ public static void main(String[] args) throws Exception{
		TestExample testExample = new TestExample(); // 如果TestExample类名上有注解@MyAnnotation修饰,则为true if(TestExample.class.isAnnotationPresent(MyAnnotation.class)){ System.out.println("There is MyAnnotation"); } Class<TestExample> c = TestExample.class; Method method = c.getMethod("read", new Class[] {}); if (method.isAnnotationPresent(MyAnnotation.class)){ // 调用read方法 method.invoke(testExample, null); // 获取方法上注解@MyAnnotation的信息 MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class); String city = myAnnotation.city(); String name = myAnnotation.name(); // 打印属性city和name的值   System.out.println(city + ", " + name); // 打印属性array数组的长度   System.out.println(myAnnotation.array().length); // 打印属性lannotation的值   System.out.println(myAnnotation.lannotation().value()); System.out.println(myAnnotation.style()); } // 得到read方法上的所有注解   Annotation[] annotations = method.getAnnotations(); for (Annotation annotation : annotations){ System.out.println(annotation.annotationType().getName()); } }  
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

谢谢阅读!

文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_40763897/article/details/104289572

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。