该文首发于我的个人博客ReadLamp
前言
注解是什么?
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
在代码方法上方常看到诸如@Override,@Deprecated这类的就叫注解。
本文主要分为以下部分:
- 基本语法
- 使用注解
- 实例演示
基本语法
在JDK中有一些已经预定义了的注解,如@Override,@Deprecated,@SuppressWarnings等
@Override:检测被该注解标注的方法是否是继承自父类(接口)
@Deprecated:表示该注解标注的内容已过时
@SuppressWarnings:压制警告一般传递参数all
例如@SuppressWarnings("all")
我们先来看看常用的@Override注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
可以看到它大抵由两部分组成:一部分是以@开头的元注解,一部分是加了@interface。通过反编译其实我们可以知道,其本质上就是一个默认继承了Annotation的接口。
既然是一个接口,那这个注解里是可以加上抽象方法的,我们在此称为属性列表。
基本格式
元注解
public @interface 注解名称{
属性列表;
}
基本的元注解
-
@Target:描述注解能够作用的位置
@Target(ElementType.TYPE)
:可以作用于类上@Target(ElementType.METHOD)
:可以作用于方法上@Target(ElementType.FIELD)
:可以作用于成员变量上
-
@Retention:描述注解被保留的阶段(生命周期)
@Retention(RetentionPolicy.RUNTIME)
:当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
-
@Documented:描述注解是否被抽取到api文档
-
@Inherited:描述注解是否被子类继承
实例演示
Check注解代码:
//如果要在程序运行时处理注解,那么必须将注解的声明周期声明为: @Retention(RetentionPolicy.RUNTIME) 。
//注意要是没有@Retention(RetentionPolicy.RUNTIME)注解,则不会被保留在字节码文件中,即无法在if (method.isAnnotationPresent(Check.class))中检测到
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
由于注解本身是不包含任何业务逻辑的,在运行时中,我们就可以通过反射来实现具体的逻辑。
关于反射相关知识请参考我的另一篇博客
执行含Check注解的方法的类 :
public class CheckTest {
public static void main(String[] args) throws Exception {
//获取配置文件对象
Properties properties = new Properties();
//通过本类类名的class获得构造器,再通过配置文件名获得资源流
InputStream resourceAsStream = CheckTest.class.getClassLoader().getResourceAsStream("com/readlamp/pro.properties");
//使配置文件对象加载资源流(理解为该对象已经可以读取配置文件的信息了)
properties.load(resourceAsStream);
//获得需要的数据
String className = properties.getProperty("className");
//Class用于新建对象与获得方法
Class cla = Class.forName(className);
//对象用以执行方法
Object o = cla.newInstance();
//获取方法
Method[] methods = cla.getMethods();
//用以记录异常出现的次数
int number = 0;
//循环执行类中待测试的方法
for (Method method : methods) {
//判断是否含有Check注解,注意Check上要有@Retention(RetentionPolicy.RUNTIME)元注解
if (method.isAnnotationPresent(Check.class)) {
try {
method.invoke(o);
} catch (Exception e) {
number++;
System.out.println("-------------------------");
System.out.println(method.getName() + "出现异常");
System.out.println("异常名称:" + e.getCause().getClass().getSimpleName());
System.out.println("异常原因:" + e.getCause().getMessage());
System.out.println("-------------------------");
}
}
}
System.out.println("共出现" + number + "次异常");
}
}
后记
在实际情况中,大多数时候我们都是使用已经定义好的注解,而不是自定义注解。
参考资料: