Java基础笔记(注解)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38801354/article/details/83048580

1 注解

注解是放在Java源码的类、方法、字段、参数前的一种标签。
注解本身对代码的逻辑没有任何影响,如何使用注解是由工具决定的,比如编译器可以使用注解,它可以使用JDK定义的注解,注解本身对代码没有影响,但写了注解,编译器可以帮我们检查问题,不写就不检查,JDK定义的常用注解有:

  • @Override:让编译器检查该方法是否正确地实现覆写
  • @Deprecated:告诉编译器该方法已经作废,在别处使用会出现警告
  • @SuppressWarning:取消警告

1.1 定义注解

使用注解的时候可以传入配置参数,配置参数在创建注解类型时定义,配置参数可以包括:

  • 所有基本类型
  • String
  • 枚举类型
  • 基本类型的数组

传入配置参数必须是常量而不能是变量,如果缺少某个配置参数将使用默认值,如果只写常量,相当于将该常量赋值给 value 参数,如果只写注解,相当于全部使用默认值。

定义注解的时候,使用 @interface 定义注解

  • 注解的参数声明类似声明一个无参数方法
  • 可以设定一个默认值
  • 推荐把最常用的参数命名为 value

eg:

public @interface Report {
	int type() default 0;
	String value() default "";
}

1.1.1 元注解

有一些注解可以修饰其他的注解,把这些注解称为元注解。

1.1.1.1 @Target 注解

使用 @Target 注解可以规定被修饰的注解能应用在源码的哪个位置:

  • ElementType.TYPE:类或接口
  • ElementType.FIELD:字段
  • ElementType.METHOD:方法
  • ElementType.CONSTRUCTOR:构造方法
  • ElementType.PARAMETER:方法参数

eg:

@Target({
	ElementType.FIELD,
	ElementType.METHOD
})
public @interface Report {
	int type() default 0;
	String value() default "";
}

1.1.1.2 @Retention 注解

@Retention 用于定义被修饰注解的生命周期:

  • RetentionPolicy.SOURCE:仅编译期,编译器在编译的时候直接丢弃,比如 @Override
  • RetentionPolicy.CLASS:仅 class 文件,该注解仅存在 class 文件中,不会被读取,有些工具可以处理 class 文件,这些工具就可以读取这个注解
  • RetentionPolicy.RUNTIME:仅运行期,在运行期可以通过代码读取该注解

如果没有 @Retention 注解,那么注解本身的生命周期默认为 CLASS,通常自定义的注解应该都是 RUNTIME

1.1.1.3 Repeatable 注解

Repeatable 注解修饰的注解可以重复注解,比如:

@Repeatable
@Target(ElementType.TYPE`)
public @interface Report {
	int type() default 0;
	String value() default "";
}

// 重复使用
@Report(type=1)
@Report(type=2)
public class Hello {
}

1.2 处理注解

因为通常写的代码并不涉及到编译器,class 文件中的注解也很少会用到,所以这里处理的注解主要针对的是运行期可以被读取的注解,也就是 Runtime 类型的注解。
如何读取 Runtime 的注解?方法是通过 反射
因为 Annotaion 也是 class,所有的 Annotation 都继承自 java.lang,annotation.Annotation,使用 反射API 就可以获取这些 Annotation
使用 反射API 确定一个 Annotation(注解)是否存在:

  • Class.isAnnotationPresent(Class)
  • Field.isAnnotationPresent(Class)
  • Method.isAnnotationPresent(Class)
  • Constructor.isAnnotationPresent(Class)

eg:

Class cls = Person.class;
// 判断 @Report 是否存在
cls.isAnnotationPresent(Report.class); // 返回布尔值

使用 反射API 获取一个 Annotation(注解):

  • Class.getAnnotation(Class)
  • Field.getAnnotation(Class)
  • Method.getAnnotation(Class)
  • Constructor.getAnnotation(Class)

eg:

class cls = Person.class;
Report report = cls.getAnnotion(Report.class); // 如果不存在,返回 null
int type = report.type();

详情通过反射读取注解,处理注解的代码,可以查看我的github

获取方法参数的 Annotation 比较麻烦,因为一般的方法可能有多个参数,同时参数本身也可以有多个注解,此时使用的是 Method.getParemterAnnotations() 方法获取一个 Anntation 的二维数组,第一个维度代表的是参数的个数,第二个维度代表的是每个参数本身自带的注解个数。

猜你喜欢

转载自blog.csdn.net/qq_38801354/article/details/83048580