注解(Annotation)
注解和接口,类一样,都是属于数据类型
注解可以在变量,方法,类之上加载
注解可以有属性也可以没有属性 @Override @Test(timeout=100)
注解作用范围(源码,编译期间,运行期间)
预定义注解
@Override
@Override就是用来指定方法覆载的,它可以强制一个子类必须覆盖父类的方法。
作用:是告诉编译器检查这个方法保证父类要包含一个被该方法重写的方法,否则就会编译出错。
只能修饰方法
@Deprecated
@Deprecated用于表示某个元素(类、方法等)已过时,当其他程序使用已过时的类、方法时。编译器将会给出警告。
修饰接口、类、方法。
@SuppressWarnings
@SuppressWarnings指示被该Annotation修饰的程序元素(以及该程序元素中的所有子元素)取消显示指定的编译器警告。该注解会一直作用于该程序元素的所有子元素。
一般传递参数all,@SuppressWarnings("all")
修饰类
@SafeVarargs
jdk1.7+
抑制堆污染警告提供的注解修饰符
修饰方法、构造器
@FunctionalInterFace
jdk1.8+
用来指定某个接口必须是函数式接口。
只能修饰接口
元注解
@Retention
描述注解被保留的阶段
value值:
RetentionPolicy.RUNTIME:保留到运行时 RetentionPolicy.CLASS):默认值,编译器把注解记录在class文件中,当运行java程序时,jvm不可获取注解信息。 RetentionPolicy.SOURCE:将被编译器直接丢弃
@Target
用于指定被修饰的注解能用于修饰哪些程序单元
value值:
ElementType取值:
ANNOTATION_TYPE //只能修饰注解 CONSTRUCTOR //只能修饰构造器 FIELD //只能修饰成员变量 LOCAL_VARIABLE //只能修饰局部变量 METHOD //只能修饰方法 PACKAGE //只能修饰包 PARAMETER //可以修饰参数 TYPE //修饰类,接口(包括注释类型)或枚举 TYPE_PARAMETER //键入参数声明 TYPE_USE //使用类型
@Target(value={ElementType.TYPE,ElementType.METHOD})
@Documented
@Documented用于指定被该元注解修饰的注解类被javadoc工具提取成文档,如果定义了注解类时使用了该注解修饰,则所有使用该注解修饰的程序元素的API文档中将会包含该注解说明。
@Inherited
@Inherited元注解指定被它修饰的注解将具有继承性——如果某个类使用了@Xxx注解(定义该注解时使用了@Inherited修饰) 修饰,则其子类将自动被@Xxx修饰。
自定义注解
注解本质上就是一个接口,该接口默认继承Annotation接口
自定义注解语法
元注解
public @interface 注解名称{
public 属性类型 属性名称();
public 属性类型 属性名称() default 默认值;
}
属性的返回值类型
基本数据类型
String
枚举
注解
以上类型的数组
注解给谁用?
编译器
给解析程序用
注解不是程序的一部分,可以理解为注解就是一个标签
example
//注解使用类
package cn.itcast.annotation.demo;
//小明定义的计算器类
public class Calculator {
//加法
@Check
public void add(){
String str = null;
str.toString();
System.out.println("1 + 0 =" + (1 + 0));
}
//减法
@Check
public void sub(){
System.out.println("1 - 0 =" + (1 - 0));
}
//乘法
@Check
public void mul(){
System.out.println("1 * 0 =" + (1 * 0));
}
//除法
@Check
public void div(){
System.out.println("1 / 0 =" + (1 / 0));
}
public void show(){
System.out.println("永无bug...");
}
}
//注解类
package cn.itcast.annotation.demo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
//注解框架
package cn.itcast.annotation.demo;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 简单的测试框架
*
* 当主方法执行后,会自动自行被检测的所有方法(加了Check注解的方法),判断方法是否有异常,记录到文件中
*/
public class TestCheck {
public static void main(String[] args) throws IOException {
//1.创建计算器对象
Calculator c = new Calculator();
//2.获取字节码文件对象
Class cls = c.getClass();
//3.获取所有方法
Method[] methods = cls.getMethods();
int number = 0;//出现异常的次数
BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
for (Method method : methods) {
//4.判断方法上是否有Check注解
if(method.isAnnotationPresent(Check.class)){
//5.有,执行
try {
method.invoke(c);
} catch (Exception e) {
//6.捕获异常
//记录到文件中
number ++;
bw.write(method.getName()+ " 方法出异常了");
bw.newLine();
bw.write("异常的名称:" + e.getCause().getClass().getSimpleName());
bw.newLine();
bw.write("异常的原因:"+e.getCause().getMessage());
bw.newLine();
bw.write("--------------------------");
bw.newLine();
}
}
}
bw.write("本次测试一共出现 "+number+" 次异常");
bw.flush();
bw.close();
}
}