java retention注解
Retention 注解
Retention(保留) 注解说明, 这种类型的注解会被保留到那个阶段. 有三个值:
1.RetentionPolicy.SOURCE —— 这种类型的 Annotations 只在源代码级别保留, 编译时就会被忽略
2.RetentionPolicy.CLASS —— 这种类型的 Annotations 编译时被保留, 在 class 文件中存在, 但 JVM 将会忽略
3.RetentionPolicy.RUNTIME —— 这种类型的 Annotations 将被 JVM 保留, 所以他们能在运行时被 JVM 或其他使用反射机制的代码所读取和使用.
示例 5 演示了 RetentionPolicy.RUNTIME 的声明:
Java 注解的示例 1:
@Retention(RetentionPolicy.RUNTIME)
public @interface Test_Retention {
String doTestRetention();
}
在这个示例中, @Retention(RetentionPolicy.RUNTIME) 注解表明 Test_Retention 注解将会由虚拟机保留, 以便它可以在运行时通过反射读取.
结论
本文向你展示了如何通过使用 JDK5 的注解功能使开发更容易. 注解不直接影响程序的语义. 开发和部署工具可以以某种方式阅读这些注解并处理它们, 使用包含注解的程序可以替代额外的 Java 源文件、XML 文档或其他古老的构件. 使用注解可以使用更少的代码完成同样的事情, 并且有更好的编译时错误检测机制. 注解的目的是花更少的时间在那些死硬无用的细节中, 更多地关注业务逻辑规则.
注解的定义:
注解的定义使用关键词 @interface , 并在上面一行注明 @Rentention(arg) 或者 @Target(args) , 样例如下:
@Rentention(RetentionPolicy.RUNTIME)
public @interface Annotation01 {
// 定义公共的 final 静态属性
.....
// 定以公共的抽象方法
......
}
常见基本内置注解
@Override 当我们想重写一个方法时,在方法上加 @Override,当我们方法的名字出错时,编译器就会报错。 定义如下:
@Retention(RetentionPolicy.SOURCE )
Java用 @interface Annotation{ } 定义一个注解 @Annotation,一个注解是一个类。
@Override,@Deprecated,@SuppressWarnings为常见的 3 个注解。
注解相当于一种标记,在程序中加上了注解就等于为程序加上了某种标记,以后,
JAVAC 编译器,开发工具和其他程序可以用反射来了解你的类以及各种元素上有无任何标记,看你有什么标记,就去干相应的事。
Java用 @interface Annotation{ } 定义一个注解 @Annotation,一个注解是一个类。
@Override,@Deprecated,@SuppressWarnings为常见的 3 个注解。
注解相当于一种标记,在程序中加上了注解就等于为程序加上了某种标记,以后,
JAVAC 编译器,开发工具和其他程序可以用反射来了解你的类以及各种元素上有无任何标记,看你有什么标记,就去干相应的事。
注解 @Override 用在方法上,当我们想重写一个方法时,在方法上加 @Override,当我们方法
的名字出错时,编译器就会报错,如图:
注解 @Deprecated,用来表示某个类的属性或方法已经过时,不想别人再用时,在属性和方法
上用 @Deprecated 修饰,如图:
注解 @SuppressWarnings 用来压制程序中出来的警告,比如在没有用泛型或是方法已经过时的时候,
如图:
注解 @Retention 可以用来修饰注解,是注解的注解,称为元注解。
Retention 注解有一个属性 value,是 RetentionPolicy 类型的,Enum RetentionPolicy 是一个枚举类型,
这个枚举决定了 Retention 注解应该如何去保持,也可理解为 Rentention 搭配 RententionPolicy 使用。RetentionPolicy 有 3 个值:CLASS RUNTIME SOURCE
用 @Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在 class 文件 (字节码文件) 中当程序编译时,但不会被虚拟机读取在运行的时候;
用 @Retention(RetentionPolicy.SOURCE) 修饰的注解, 表示注解的信息会被编译器抛弃,不会留在 class 文件中,注解的信息只会留在源文件中;
用 @Retention(RetentionPolicy.RUNTIME)修饰的注解,表示注解的信息被保留在 class 文件 (字节码文件) 中当程序编译时,会被虚拟机保留在运行时,
所以他们可以用反射的方式读取。RetentionPolicy.RUNTIME 可以让你从 JVM 中读取 Annotation 注解的信息,以便在分析程序的时候使用.
- package com.self;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyTarget
- { }
- 定义个一注解@MyTarget,用 RetentionPolicy.RUNTIME 修饰;
- package com.self;
- import java.lang.reflect.Method;
- public class MyTargetTest
- {
- @MyTarget
- public void doSomething()
- {
- System.out.println("hello world");
- }
- public static void main(String[] args) throws Exception
- {
- Method method = MyTargetTest.class.getMethod("doSomething",null);
- if(method.isAnnotationPresent(MyTarget.class))// 如果 doSomething 方法上存在注解 @MyTarget,则为 true
- {
- System.out.println(method.getAnnotation(MyTarget.class));
- }
- }
- }
- 上面程序打印:@com.self.MyTarget(),如果 RetentionPolicy 值不为 RUNTIME, 则不打印。
- @Retention(RetentionPolicy.SOURCE )
- public @interface Override
- @Retention(RetentionPolicy.SOURCE )
- public @interface SuppressWarnings
- @Retention(RetentionPolicy.RUNTIME )
- public @interface Deprecated
- 由上可以看出,只有注解@Deprecated 在运行时可以被 JVM 读取到
- 注解中可以定义属性,看例子:
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyAnnotation
- {
- String hello() default "gege";
- String world();
- int[] array() default { 2, 4, 5, 6 };
- EnumTest.TrafficLamp lamp() ;
- TestAnnotation lannotation() default @TestAnnotation(value = "ddd");
- Class style() default String.class;
- }
- 上面程序中,定义一个注解@MyAnnotation,定义了6 个属性,他们的名字为:
- hello,world,array,lamp,lannotation,style.
- 属性 hello 类型为 String, 默认值为 gege
- 属性 world 类型为 String, 没有默认值
- 属性 array 类型为数组, 默认值为2,4,5,6
- 属性 lamp 类型为一个枚举, 没有默认值
- 属性 lannotation 类型为注解, 默认值为@TestAnnotation,注解里的属性是注解
- 属性 style 类型为 Class, 默认值为 String 类型的 Class 类型
- 看下面例子: 定义了一个 MyTest 类,用注解@MyAnnotation 修饰,注解@MyAnnotation 定义的属性都赋了值
- @MyAnnotation(hello = "beijing", world="shanghai",array={},lamp=TrafficLamp.RED,style=int.class)
- public class MyTest
- {
- @MyAnnotation(lannotation=@TestAnnotation(value="baby"), world = "shanghai",array={1,2,3},lamp=TrafficLamp.YELLOW)
- @Deprecated
- @SuppressWarnings("")
- public void output()
- {
- System.out.println("output something!");
- }
- }
- 接着通过反射读取注解的信息:
- public class MyReflection
- {
- public static void main(String[] args) throws Exception
- {
- MyTest myTest = new MyTest();
- Class<MyTest> c = MyTest.class;
- Method method = c.getMethod("output", new Class[] {});
- // 如果 MyTest 类名上有注解 @MyAnnotation 修饰,则为 true
- if(MyTest.class.isAnnotationPresent(MyAnnotation.class))
- {
- System.out.println("have annotation");
- }
- if (method.isAnnotationPresent(MyAnnotation.class))
- {
- method.invoke(myTest, null); // 调用 output 方法
- // 获取方法上注解 @MyAnnotation 的信息
- MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
- String hello = myAnnotation.hello();
- String world = myAnnotation.world();
- System.out.println(hello + ", " + world);// 打印属性 hello 和 world 的值
- System.out.println(myAnnotation.array().length);// 打印属性 array 数组的长度
- System.out.println(myAnnotation.lannotation().value()); // 打印属性 lannotation 的值
- System.out.println(myAnnotation.style());
- }
- // 得到 output 方法上的所有注解,当然是被 RetentionPolicy.RUNTIME 修饰的
- Annotation[] annotations = method.getAnnotations();
- for (Annotation annotation : annotations)
- {
- System.out.println(annotation.annotationType().getName());
- }
- }
- }
- 上面程序打印:
- have annotation
- output something!
- gege, shanghai
- 3
- baby
- class java.lang.String
- com.heima.annotation.MyAnnotation
- java.lang.Deprecated
- 如果注解中有一个属性名字叫 value, 则在应用时可以省略属性名字不写。
- 可见,@Retention(RetentionPolicy.RUNTIME ) 注解中,RetentionPolicy.RUNTIME 是注解属性值,属性名字是 value,
- 属性的返回类型是 RetentionPolicy,如下:
- public @interface MyTarget
- {
- String value();
- }
- 可以这样用:
- @MyTarget("aaa")
- public void doSomething()
- {
- System.out.println("hello world");
- }
- 注解@Target 也是用来修饰注解的元注解,它有一个属性 ElementType 也是枚举类型,
- 值为:ANNOTATION_TYPE CONSTRUCTOR FIELD LOCAL_VARIABLE METHOD PACKAGE PARAMETER TYPE
- 如@Target(ElementType.METHOD) 修饰的注解表示该注解只能用来修饰在方法上。
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyTarget
- {
- String value() default "hahaha";
- }
- 如把@MyTarget 修饰在类上,则程序报错,如:
- @MyTarget
- public class MyTargetTest
- 注解大都用在开发框架中吧,好了有关注解就学习那么多了,谢谢。
- 本文转自 http://blog.csdn.net/liuwenbo0920/article/details/7290586/