注解
注解是什么?
注解时代码里的特俗和标记, 这些标记可以在类编译\加载\运行时被读取, 并执行相应的处理.
程序员可以在不改变原有逻辑的情况下, 嵌入一些补充信息
注解分类有哪些?
-
文档类注解
- author
- version
-
编译时格式检查(JDK内置的三个基本注解)
-
@Deprecated
-
@Override: 编译时强制校验该方法是不是重写的, 良好的提示
-
@SuppressWarnings: 抑制编译器警告
- @SuppressWarnings({“unused”, “rawtypes”})
-
-
跟踪代码的依赖性, 实现替代配置文件的功能
- Servlet中使用的web.xml可以是h使用@WebServlet(“xxx”)来替换
- Spring中关于事务的管理
如何自定义注解?
参照@SuppressWarnings
-
注解声明为@interface, 自动继承了java.lang.annotation.Annotation接口
-
内部定义成员, 通常使用value表示
- 成员变量在定义中, 以无参方法的方式进行声明, 方法名和返回值定义了该成员的名字和类型, 称为配置参数. 只能是八种基本数据类型/String/Class/Annotation以及其所对应的数组
- 如果只有一个参数成员, 建议使用参数名为value
-
可以指定成员的默认值, 使用default定义
- 如果定义的注解含有配置参数, 使用时必须指定参数值, 除非有默认值, 格式是“
参数名=参数值
”, 如果只有一个参数成员并且参数名为value则可以省略value=
- 如果定义的注解含有配置参数, 使用时必须指定参数值, 除非有默认值, 格式是“
-
如果自定义在注解没有成员, 表示是一个标识作用
- 没有成员定义的Annotation称为标记(例如 Override); 包含成员变量的Annotation称为元数据
public @interface myDefinedAnnotation{ String value() default "hello"; //String value(); //多个值可以使用数组 //String value()[]; }
@myDefinedAnnotation class Person{}
自定义注解需要配上相应的的信息处理流程
JDK中的元注解
对现有注解进行解释说明的注解
@Retention
指明修饰注解的生命周期
- SOURCE: class文件中没有
- CLASS: 保留在class文件中, 运行时不加载在内存中
- RUNTIME: 加载在内存中, 可以通过反射读取
例如: SuppressWarnings: 仅用于在编译时校验, 生命周期较短
@Target
该注解能够修饰那些结构
@Documented
表示所修饰的注解, 在被javadoc解析时, 保留下来(@Deprecated)
@Inherited
被修饰的注解将具有继承性,例如:
@Inherited
public @interface myDefinedAnnotation{
String value();
}
@myDefinedAnnotation
class Person{}
//Person类有子类Student类
class Student extends Person{}//Student类也将具有@myDefinedAnnotation注解
通过反射获取注解
public class testAnnotation {
@Test
public void testAnnotation() {
Class clazz = Student.class;
Annotation[] clazzAnnotations = clazz.getAnnotations();
for (Annotation a : clazzAnnotations) {
System.out.println(a);
}
}
}
@myDefinedAnnotation("hello")
class Person {
}
class Student extends Person {
}
其中自定义注解的定义如下:
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface myDefinedAnnotation {
String value();
}
需要注意的是, 需要将生命周期设置为Runtime, 才能够在程序运行时获取(本例为遍历操作). 另外可以看到, 当注解被@Inherited修饰之后, 被@myDefinedAnnotation修饰的Person其子类Student也具有了该注解和对应的取值.
注解的新特性
最终都是为了: 反射拿到注解内容然后做点额外的事
可重复注解
之前如果需要两个注解@myDefinedAnnotation("hello")
和@myDefinedAnnotation("hi")
,
做法是再写一个注解的数组:
public @interface MyAnnotation{
myDefinedAnnotation[] value();
}
再在Person的注解上补充:
MyAnnotation({@myDefinedAnnotation("hello"),@myDefinedAnnotation("hi")})
class Person {
}
新特性中, 可以通过在@myDefinedAnnotation添加元注解@Repeatable(Mynnotation.class)
补充, 来实现可重复注解:
@Retention(Runtime)
@Target(class, method)
public @interface MyAnnotation{
myDefinedAnnotation[] value();
}
@Repeatable(Mynnotation.class)
@Retention(Runtime)
@Target(class, method)
public @interface myDefinedAnnotation{
String value();
}
如此可以在Person类中添加重复注解, 即
@myDefinedAnnotation("hello")
@myDefinedAnnotation("hi")
class Person{}
需要注意的是, 除@Repeatable这一元注解外,其余@Retention和@Inherited 以及@Target这些都必须保持一致
类型注解
注解可以修饰泛型
class Genertic<@myDefinedAnnotation T>{
public void show();
}
需要在@myDefinedAnnotation中的@Target元注解中加入:TYPE_PARAMETERdeng修饰