文章目录
为什么使用注解
在没有注解之前,XML被用于描述数据,各大框架广泛应用,以松耦合的方式完成了框架中的所有配置,但是随着项目越来越庞大,XML配置的东西就越来越多,维护就变得异常困难。所以就有人提出了一种标记式高耦合的配置方式“注解”,可以把相关配置直接和代码强耦合。
什么是注解
从JDK5开始,Java增加对元数据(描述数据属性的信息)的支持,也就是注解,注解和注释是有一定的区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译、类加载和运行时被读取,并执行相应操作,通过注解开发人员可以在不改变原有代码和逻辑的情况下,在源代码中嵌入补充信息。注解可以对包、类、接口、字段、方法、参数、变量和构造方法等进行注解。如果不处理注解,注解连注释都不如。
注解分类
- 元注解:用于定义注解的注解,@Retention、@Target、@Documented、@Inherited和@Repeatable。
- Java基本注解:@Override、@Deprecated、@SuppressWarnings、@SafeVarargs和@Functionallnterface。
- 自定义注解:根据自己使用定义注解。
JDK元注解
元注解的作用就是负责解释其他注解:
@Retention
修饰注解可以使用多久,参数类型是RetentionPolicy,且仅有三个值:
参数 | 作用 | 备注 |
---|---|---|
RetentionPolicy.CLASS | 注解记录在class文件中,运行时JVM不可获取 | 默认值 |
RetentionPolicy.RUNTIME | 注解记录在class文件中,运行时JVM可以获取 | 可以通过反射获取注解信息 |
RetentionPolicy.SOURCE | 注解只保存载源码中,编译直接丢弃 |
例如:
@Retention(valuer= RetentionPolicy.SOURCE)
//也可以省略value =
@Retention(RetentionPolicy.CLASS)
@Target
修饰注解能用于修饰哪些程序单元,参数类型是ElementType数组,有以下几种:
参数 | 作用 | 备注 |
---|---|---|
ElementType.METHOD | 用于方法上 | 不可用于构造方法 |
ElementType.TYPE | 用于类或者接口上 | |
ElementType.ANNOTATION | 用于注解上 | 被@interface修饰的类型 |
ElementType.CONSTRUCTOR | 用于构造方法上 | |
ElementType.FIELD | 用于域上 | |
ElementType.LOCAL_VARIABLE | 用于局部变量上 | |
ElementType.PACKEG | 用于记录Java文件的package信息 | |
ElementType.PARAMETER | 用于参数上 |
例如写一个自定义注解用于方法、类和接口上:
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface myAnno{
}
@Documented
被修饰的注解将被javadoc工具提取成文档。
@Inherited
被修饰的注解将具有继承性,例如某个类使用的@myAnno,则其子类将自动被@myAnno修饰。
@Repeatable
被修饰的注解可以在一个程序单元被多次使用。
Java基本注解
@Override
子类重写父类加上这个注解可以避免低级错误,例如参数类型错误和方法名错误等。
@Deprecated
标记过时,被标记的方法或者类等使用的时候会有删除线,但是可以使用。
@SuppressWarnings
被标记的单元取消编译警告,例如在idea中声明一个方法不使用,那么这个方法名是灰色会有警告,加上此注解就不会警告。
@SafeVarargs
在声明具有模糊类型(比如:泛型)的可变参数的构造函数或方法时,Java编译器会报unchecked警告。鉴于这些情况,如果程序员断定声明的构造函数和方法的主体不会对其varargs参数执行潜在的不安全的操作,可使用@SafeVarargs进行标记,这样的话,Java编译器就不会报unchecked警告。
@Functionallnterface
保证接口中只能有一个抽象方法(可以有多个默认方法和静态方法),只能用于修饰接口。
自定义注解
自定义注解很简单,用@interface关键字,例如:
public @interface myAnno{
}
在其它地方就可以使用:
@myAnno
public class myClass{
@myAnno
public void myMethod(){
}
}
注解的成员变量:
public @interface myAnno{
String value();
int type() default 0;
}
注解中的成员变量是以方法的形式来定义的,注解的成员变量如没有默认值的,在使用注解的时候就必须传入参数,例如:
@myAnno("class")
public class myClass{
@myAnno(type=10,value="method")
public void myMethod(){
}
}
注解的参数没有顺序。也可以用元注解来修饰自定义注解,参照元注解的内容。
注解的用途
- 生成文档:通过代码里标识的元数据生成javadoc文档。
- 编译检查:通过代码里标识的元数据让编译器在编译期间检查验证。
- 编译时动态处理:编译时期通过代码里标识的元数据动态生成代码。
- 运行时动态处理:运行时通过代码里的标识元数据动态处理,如反射注入实例。