注解本质上也是一个类,但用法比较特殊。注解可以被标注在任意地方,包括方法上、类名上、参数上、成员属性上、注解定义上等,就像注释一样,它相当于我们对某样东西的一个标记。而与注释不同的是,注解可以通过反射在运行时获取,注解也可以选择是否保留到运行时。

声明一个注解类型:

@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));
分类: JAVA SE

0 条评论

发表评论

邮箱地址不会被公开。