【Java】注解
注解不等于注释,注解可以理解为有功能的注释
二者都是对程序的一些解释说明,但区别在于注解是可以被其他程序(如编译器)所读取的,而注释仅仅只供人类阅读
内置注解
- @Override 表示该方法是在重写父类方法,确保子类中的方法签名与父类中被覆盖的方法的签名一致,避免由于拼写错误、参数类型错误等导致的意外行为
- @Deprecated 表示方法、类或字段不建议使用(或很危险或有更好的选择)
- @SuppressWarnings 告诉编译器忽略指定类型的警告信息,用来抑制警告
另外还有@SafeVarargs和@FunctionalInterface,由于使用频率不高,这里暂且按下不表。
元注解
负责注解其他注解
- @Target,注解使用的范围(类、方法、构造器等,详见下面的展开阐述)
- @Retention,注解生命周期)
- @Documented,是否生成到javadoc中
- @Inherited,子类可继承父类的注解
Target
Target中的指定通过 ElementType.[placeholder] 形式来制定,[]中可能的取值有:
TYPE: 表示可以应用于类、接口(包括注解类型)或枚举声明。
FIELD: 表示可以应用于字段(包括枚举常量)声明。
METHOD: 表示可以应用于方法声明。
PARAMETER: 表示可以应用于参数声明。
CONSTRUCTOR: 表示可以应用于构造函数声明。
LOCAL_VARIABLE: 表示可以应用于局部变量声明。
ANNOTATION_TYPE: 表示可以应用于注解类型声明(即注解的声明)。
PACKAGE: 表示可以应用于包声明。
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyAnnotation {
// 注解的属性
}
Retention
类似与@Target,其同样是通过指定 RetentionPolicy.[placeholder],[]可能的取值有:
SOURCE: 注解仅保留在源代码中,编译时会被丢弃,不会包含在编译后的类文件中。即注解只对编译器可见,对运行没有任何影响。
CLASS: 注解保留在编译后的类文件中,但在运行时不可访问。即注解对反射是不可见。
RUNTIME: 注解保留在编译后的类文件中,并且在运行时可以通过反射获取。
从上到下依次是包含关系,也即class有效,那么source也有效。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
// 注解的属性
}
@Documented
用于指定自定义注解是否应该被 javadoc 工具记录,若注解被 @Documented 修饰,在使用 javadoc 工具生成 API 文档时会包含该注解
其不像上面两个注解可以指定属性,使用时直接修饰相应的注解即可
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
// 注解的属性
}
@Inherited
用于指定自定义注解是否具有继承性(当一个类使用了该注解时,其子类是否会继承该注解)
但需要注意的是,@Inherited 只对类的继承关系有效,对接口、字段、方法等的继承关系不起作用。
和@Documented一样,@Inherited使用时也是直接修饰即可。
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
// 注解的属性
}
自定义注解
类似于定义接口,只不过使用的关键字是@interface。
public @interface MyAnnotation {
// 注解的属性
}
自定义注解中还可以定义若干属性,其格式为:
参数类型 + 参数名()
这是命名要求,一定要遵守(注意和方法的括号区分)
public @interface MyAnnotation {
String value(); // 定义一个属性 value
int count() default 1; // 定义一个属性 count,默认值为 1
}
MyAnnotation 注解定义了两个属性,一个是名为 value 的字符串类型属性,另一个是名为 count 的整型属性,并且给 count 属性设置了默认值为 1。
@MyAnnotation(value = "example", count = 2)
public class MyClass {
// 类体
}
注意,若注解只有一个属性,那么属性名使用value,如是在使用该注解时可以省略属性名,直接为属性赋值
另外,注解不像函数,参数传入没有顺序。