什么是注解?
Java注解(Annotation)是一种元数据(Metadata)机制,可以为Java代码提供更丰富的语义信息。它是一种标记,可以被添加到Java源代码中的类、方法、字段、参数等元素上,用于说明这些元素的用途、属性或约束条件等信息。Java注解是JDK5.0中引入的新特性,它广泛应用于Java EE框架、Spring、JUnit等开发领域,以及各种代码生成工具和IDE插件中。Java注解的使用形式类似于Java注释,但注解具有更强的语义性和可扩展性。
注解的作用
- 生成文档
- 跟踪代码依赖性。
- 编译时进行格式检查。
注解的分类
注解主要分为三类
元注解:元注解是可以注解到注解上的注解。
标准注解:Java自带的注解,有特定的用处。
自定注解:开发中根据需求自己创建的注解。
元注解
元注解的作用就是负责注解其他注解
@Documented
作用:如果一个注解@Ex被@Documented修饰,那么被@Ex修饰的类,在生成文档时,会显示@Ex注解。如果@Ex没有被@Documented修饰,则最终生成文档中就不会有@Ex注解。
@Retention
作用:用来表示注解的生命周期,生命周期的长短取决于其属性RetentionPolicy的值。
参数详解:
值 | 详细描述 | 作用范围 | 使用场景 |
---|---|---|---|
RetentionPolicy.SOURCE | 表示注解只保留在源文件中,当Java文件编译成class文件后就会消失 | 源文件 | 做代码检查时,例如@Override和@SuppressWarning |
RetentionPolicy.CLASS | 表示注解会保留到class文件中,但jvm加载class文件的时候就会消失 | class文件 (默认) | 需要在编译时进行一些处理操作,比如一些辅助代码 |
RetentionPolicy.RUNTIME | 表示注解会保存到class文件中,并且jvm在加载class文件后,注解依然存在 | 运行时也存在 | 需要在运行时动态获取注解信息 |
生命周期排序:SOURCE < CLASS < RUNTIME
@Target
作用:表示注解的作用范围,如果超出范围,在编译时就会报错,范围由参数规定。
参数详解:
参数 | 范围 |
---|---|
ElementType.TYPE | 接口、类、枚举类、注解 |
ElementType.FIELD | 字段、枚举常量 |
ElementType.METHOD | 方法 |
ElementType.PARAMETER | 方法参数 |
ElementType.CONSTRUCTOR | 构造函数 |
ElementType.LOCAL_VARIABLE | 局部变量 |
ElementType.ANNOTATION_TYPE | 注解 |
ElementType.PACKAGE | 包 |
用法举例:@Target(ElementType.TYPE)
@Inherited
作用:如果一个类上使用了这个注解修饰的注解,那么其子类也会继承这个注解。
注意:
- 接口上使用@Inherited修饰的注解,其实现类不会继承这个注解。
- 父类的方法使用@Inherited修饰的注解,子类不会继承这个注解。
在使用反射技术时,当父类的注解中用@Inherited修饰,子类的getAnnotations()才能获取得到父亲的注解以及自身的注解,而getDeclaredAnnotations()只会获取自身的注解,无论如何都不会获取父亲的注解。
标准注解
@Override
作用:说明该方法是从父类或者接口中继承过来的,需要重写。
@FunctionalInterface
作用:用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口的定义时,编译器会报错。
函数式接口:函数式接口首先必须是一个接口,接口里面只能有一个抽象方法(允许有默认方法、静态方法等);这种类型的接口也称为SAM接口,即Single Abstract Method Interface。
@Suppresswarnings
作用:屏蔽一些无关紧要的警告。使开发者能看到一些他们真正关心的警告。从而提高开发者的效率。屏蔽的内容由参数决定。
参数详解:
参数 | 作用 |
---|---|
all | 屏蔽所有警告 |
boxing | 屏蔽装箱、拆箱时的警告 |
cast | 屏蔽映射相关的警告 |
dep-ann | 屏蔽启用注释的警告 |
deprecation | 屏蔽过期方法警告 |
fallthrough | 屏蔽存在switch时确实breaks的警告 |
finally | 屏蔽finally没有返回的警告 |
hiding | 屏蔽相对于隐藏变量的局部变量的警告 |
incomplete-switch | 忽略不完整的switch警告 |
nls | 屏蔽非nls格式的字符 |
null | 屏蔽对null的操作 |
rawtypes | 使用generics时屏蔽没有指定相应的类型 |
restriction | 屏蔽禁止使用劝阻或禁止引用的警告 |
serial | 屏蔽在serializable类中没有声明serialVersionUID变量的警告 |
static-access | 屏蔽不正确的静态访问方式的警告 |
synthetic-access | 屏蔽子类没有按最优方法访问内部类的警告 |
unchecked | 屏蔽没有进行类型检查操作的警告 |
unqualified-field-access | 屏蔽没有权限访问的域的警告 |
unused | 屏蔽没被使用过的代码的警告 |
用法举例:
@SuppressWarnings("null")
@SuppressWarnings({null,null})
@SuppressWarnings(value={null,null})
@Deprecated
作用:表示不推荐程序员使用,但是还可以使用,编译器将会给出警告。
@SafeVarargs
作用:表示该方法必须由static或final修饰的方法。
自定义注解
创建方法:
可以在自定义注解上使用元注解对自定义注解进行修饰设置。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
}
注解的解析
自定义注解:
@Target({ElementType.CONSTRUCTOR, ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface study {
String name() default "";
int age() default 0;
String[] hobby() default {};
}
1、先利用反射获取Class对象
Class clazz = Test.class;
2、解析类上的注解,并获取值
if(clazz.isAnnotatioonPresent(Bean.class)){
study study = (study)clazz.getDeclaredAnnotation(study.class);
String name = study.name;
int age = study.age;
String[] hobby = study.hobby;
}
类、方法、构造、属性上注解的解析方式一样,都是使用反射技术来进行,反射技术详细可以参考: