1.1. 理解Java注解
所有的注解类型都继承自接口Annotation。
我们之前常用的 @Override 就是一个注解。比如实现Runnable接口的代码:
class MyRunnable implements Runnable
{
@Override
public void run()
{
System.out.println("启动新线程");
}
}
一旦编译器检测到某个方法被修饰了 @Override 注解,编译器就会检查当前方法的方法签名是否真正重写了父类的某个方法,也就是比较父类中是否具有一个同样的方法签名。
看看@Override的源码:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
反编译后会发现Override就是继承自Annotation:
public interface Override extends Annotation{
}
注解的本质就是一个继承了 Annotation 接口的接口。(接口可以继承接口,类只能实现接口)
1.2. 语法
定义一个注解:
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{
}
上面的代码中@Documented, @Target, @Retention, @interface 都是来修饰 MyAnnotation 的,叫做元注解。
1.3. 元注解
元注解是用于修饰注解的注解。
元注解分类:
@Target:注解的作用目标
@Retention:注解的生命周期
@Documented:注解是否应当被包含在 JavaDoc 文档中
@Inherited:是否允许子类继承该注解
下面我们分开讲一下:
1.3.1. @Target
@Target 用于指明被修饰的注解最终可以作用的目标是谁,也就是指明,你的注解到底是用来修饰方法的?修饰类的?还是用来修饰字段属性的。
@Target的参数ElementType 是一个枚举类型,有以下一些值:
ElementType.TYPE | 注解作用在类、接口和枚举上 |
ElementType.FIELD | 注解作用在属性字段上 |
ElementType.METHOD | 注解作用在方法上 |
ElementType.PARAMETER | 注解作用在方法参数上 |
ElementType.CONSTRUCTOR | 注解作用在构造器上 |
ElementType.LOCAL_VARIABLE | 注解作用在本地局部变量上 |
ElementType.ANNOTATION_TYPE | 注解作用在注解上 |
ElementType.PACKAGE | 注解作用在包上 |
1.3.2. @Retention
@Retention 用于指明当前注解的生命周期。
@Retention的参数RetentionPolicy 也是一个枚举类型,有以下一些值:
RetentionPolicy.SOURCE | 当前注解编译期可见,编译后会被丢弃,不会写入 class 文件 |
RetentionPolicy.CLASS | 类加载阶段丢弃,会写入 class 文件 |
RetentionPolicy.RUNTIME | 永久保存,可以反射获取 |
1.3.3. @Documented
@Documented用来注解是否应当被包含在 JavaDoc 文档中,注解以后当我们执行 JavaDoc 文档打包时会被保存进 doc 文档,反之将在打包时丢弃。
1.3.4. @Inherited
@Inherited 用来注解是否具有可继承性,也就说我们的注解修饰了一个类,而该类的子类将自动继承父类的该注解。
1.4. Java内置注解
除了上述四种元注解外,Java还有内置注解,主要有三种:
@Override
@Deprecated
@SuppressWarnings
1.4.1. @Override
用于标明此方法覆盖了父类的方法,源码如下:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
它没有任何的属性,所以并不能存储任何其他信息。它只能作用于方法之上,编译结束后将被丢弃。
1.4.2. @Deprecated
用于标明已经过时的方法或类,源码如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
1.4.3. @SuppressWarnings
用于抑制编译器产生警告信息,源码如下:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
其内部有一个String数组,主要接收值如下:
deprecation | 使用了不赞成使用的类或方法时的警告 |
unchecked | 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型 |
fallthrough | 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告 |
path | 在类路径、源文件路径等中有不存在的路径时的警告 |
serial | 当在可序列化的类上缺少 serialVersionUID 定义时的警告 |
finally | 任何 finally 子句不能正常完成时的警告 |
unused | 没有使用代码的警告 |
null | 与null分析有关的警告 |
cast | 强制转换相关的警告 |
rawtypes | 使用泛型时忽略没有指定相应的类型 |
all | 关于以上所有情况的警告 |
1.4.4. 内置注解示例
1、使用@Deprecated 示例:
//注明该类已经过时,不建议使用
@Deprecated
public class Test{
//注明该方法已经过时,不建议使用
@Deprecated
public void test()
{
}
}
2、使用@SuppressWarnings示例:
(1) 忽略不指定类型和未检查转换警告
没有使用@SuppressWarnings:
使用之后:
(2)忽略没有使用代码的警告
没有使用@SuppressWarnings:
使用之后: