注解本质上也是一个类,但用法比较特殊。注解可以被标注在任意地方,包括方法上、类名上、参数上、成员属性上、注解定义上等,就像注释一样,它相当于我们对某样东西的一个标记。而与注释不同的是,注解可以通过反射在运行时获取,注解也可以选择是否保留到运行时。
声明一个注解类型:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Test{
String value() default "这是一个注解";
}
即用@interface
来声明一个注解,注解内部可以有属性,但不能用方法,并且属性的设置方式为“无参的方法”,只能有数据类型,不能设置访问权限,可以指定默认值。
预设注解
JDK预设了一些常用的注解,作用于代码:
- @Override - 检查该方法是否是重写方法,如果其父类或者实现的接口中没有该方法那么就会编译报错!进作用在编译阶段。
- @Deprecated - 标记过时方法,比如Thread.stop(),使用这类方法时编译器会警告。
- @SuppressWarnings - 指示编译器去忽略注解中声明的警告(仅仅是编译阶段)
- @FunctionalInterface- 标记接口为函数式接口, JDK8开始支持
还有很多。
元注解
元注解用于我们编写的注解类型上,用来限制该注解的作用域:
- @Target({ElementType.METHOD, ElementType.TYPE}) - 表示该注解只能用于METHOD方法和TYPE类型上面,类型包括类、接口和枚举。ElementType里面还有其它类型,需要时可以添加。
- @Retention(RetentionPolicy.RUNTIME) - 用于指定该注解可以保留到什么时候。RUNTIME,运行时;CLASS,编译为字节码时;SOURCE,编译时。若保留到运行时可以通过反射来访问注解。
- @Documented - 标记这些注解是否包含在用户文档中。
- @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
注解的使用
对于上述自定义的注解,可以用在类或者方法上面,同时使用时必须为注解的属性进行赋值(属性有默认值时可以缺省)。
@Test(value = "这是一个类的注解")
public class Main {
@Test(value = "这是一个方法的注解")
public static void main(String[] args) {
;
}
}
注解保留到运行时的话就可以通过反射来获得注解。
Class<CookerandConsumer> clazz = CookerandConsumer.class;
for (Annotation annotation : clazz.getAnnotations()) {
System.out.println(annotation.annotationType());
if (annotation instanceof Test) {
Test test = (Test) annotation;
System.out.println(test.value());
}
}
注解也算是一个类,那么它就可以创建对象,对象可以访问其内部的属性。
可以获取到任意位置的注解,类上,接口上,方法上,属性上等等,因为它们都实现了AnnotatedElement接口,都有getAnnotations方法。
也可以获取指定的注解:
// 只想获取add方法上的Test注解。
System.out.println(clazz.getMethod("add").getAnnotation(Test.class));
0 条评论