目录
1.注解
注解就相当于一个标签,在这个标签里面可以存储一些值,在需要的时候就可以取出标签内的值使用。
2.使用注解
声明一个注解的时候, 里面的属性只能为public或者默认不写.不能为 protected 或 private.
@Retention(RetentionPolicy.RUNTIME) // 设置在运行时可以获取到注解属性
public @interface TestAnnotation1 {
// 如果只有一个value可以直接赋值,否则使用value=...
String value();
// 声明一个数组
String[] args();
// num属性的默认值为1
int num() default 1;
}
@TestAnnotation1(args = { "参数1", "参数2" }, value = "AnnotationTest", num = 123)
public class AnnotationTest {
// 给数组赋值时要用大括号括起来,参数有默认值就可以不用赋值,直接使用默认值
@TestAnnotation1(value = "value", args = { "123", "789" })
public void test() {
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
// 获取注解信息
/**
* 得到一个类的字节码有三种方式: 1.类名.class 2.类的实例.getClass() 3.Class.forName()
*/
// 获取AnnotationTest的类型信息对象
Class<?> class1 = AnnotationTest.class;
// 获取AnnotationTest类上的注解
TestAnnotation1 classAnnotation = class1.getAnnotation(TestAnnotation1.class);// 获取类上的注解信息
//获取注解信息
System.out.println(classAnnotation.num());
System.out.println(classAnnotation.value());
System.out.println(Arrays.toString(classAnnotation.args()));
//通过AnnotationTest的类信息对象获取类里面的方法
Method method = class1.getMethod("test");
// 获取方法上的注解
TestAnnotation1 methodAnnotation = method.getAnnotation(TestAnnotation1.class);
// method.getAnnotations();//获取所有的注解
System.out.println(methodAnnotation.num());
System.out.println(methodAnnotation.value());
System.out.println(Arrays.toString(methodAnnotation.args()));
}
}
3.元注解
元注解就是使用在注解上的注解.
@Documented
使用了@Documented注解后, 在生成javadoc时编译器就能够将注解中的元素包含到 Javadoc 中去。
@Retention
当 @Retention 使用到一个注解上的时候,它说明了这个注解的的存活时间。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
@Retention注解中也只有一个枚举类数组RetentionPolicy属性
- RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时(class文件)它将被丢弃(也就是说在class文件中找不到该注解)
- RetentionPolicy.CLASS 注解只被保留到编译(class文件)的时候,它并不会被加载到 JVM 中。(在class文件中存在该注解,但是在运行时无法获取该注解的属性值)
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,在程序运行时可以获取到它们。
如果在自定义一个注解的时候没有使用@Retention指定该注解的存活时间, 那么将默认为 RetentionPolicy.CLASS
@Target
@Target 指定了注解运用的地方, 如果在声明类时只指定了在方法上能够使用, 那么在其他地方使用就会报错
下面时@Target 注解的源代码
@Documented // 能够将注解中的元素包含到 Javadoc 中去。
@Retention(RetentionPolicy.RUNTIME) // 指定@Target注解的的存活时间
@Target(ElementType.ANNOTATION_TYPE) // 指定@Target注解只能在注解上使用
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();
}
@Target注解只有一个ElementType数组属性, 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
}
//该注解只能在类(类,接口,枚举类)和方法上使用
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation1 {
// 如果只有一个value可以直接赋值,否则使用value=...
String value();
// 声明一个数组
String[] args();
// num属性的默认值为1
int num() default 1;
}
@Inherited
如果在自定义注解 A 的时候使用了@Inherited , 然后使用 A 注解类 B , 这时候类 B 有一个注解 A , 如果另外一个类 C 继承了 B , 那么类 C 也会有一个注解 A.(如果在自定义注解 A 的时候没有使用@Inherited , 那么类 C 就不会有注解 A)