注解的定义
-
注解:说明程序的,是给计算机看的
-
注释:用文字描述程序的,是给程序员看的.
定义:注解也叫元数据,一种代码级别的说明,他是JDK1.5及以后版本引入的一个特性,与类, 接口,枚举是在同一个层次,他可以生命在包,类,字段,方法,局部变量,方法参数等的前面,用 来对这些元素进行说明,注释.
1.概念描述:
jdk1.5之后的新特性
说明程序的
使用注解:@注解名称
-
作用分类:
编写文档:通过代码里的标识注解生成文档doc文档
代码分析:通过代码里标识注解对代码进行分析(使用的是反射)
编译检查:通过代码里标识注解让编译器能够实现基本的编译检查 -
JDK中预定义了一些注解
@Override:标识方法是继承方法 @Deperecated:该注解标注的内容,表示已经过时了 @SuppressWarnings:压制警告 一般传递参数all @SuppressWarnings("all")
-
自定义注解:
格式: public @interface 注解名称{} 本质: 注解本质上就是一个接口,该接口默认继承Annotation接口 反编译之后 public interface 注解名称 extends Java.lang.annotation.Annotation{} 属性:接口中的抽象方法 要求: 1.属性的返回值类型: 基本数据类型 String 枚举 注解 以上类型的数组 2.public @interface MyAnno{ int age(); String name() default="张三"; } 使用该注解的时候: @MyAnno(age = 1,name="rong") 定义了属性,在使用时需要给属性赋值 1.如果定义了属性是,使用default关键字给属性默认初始化值,则使用注解时,则可以 可以使用默认值 2.如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接赋值
-
元注解:
用来描述注解的注解 @Target:描述注解能作用的位置 ElementType取值: Type:可以作用在类上 METHOD:可以作用在方法上 FIELD:可以作用在成员变量上 @Retention:描述注解能被保留的阶段(Java类加载的三个阶段) @Retention(RetentionPolicy.RUNTIME):当前被描述的注解会保留到 class字节码文件中,并被JVM读取到 @Documented:描述注解是否可以被抽取到api文档中 @Documented标识注解在生产API文档时会被保留 @Inherited:描述注解是否可以被子类继承 子类继承的时候回同时继承注解
@Target({ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface target {
}
在程序中解析注解,获取注解中的属性值
1.获取注解定义位置的对象(其中包括,class,method,Field)
2.获取指定的注解
例如class的
//3.获取注解对象
//其实就是在内存中创建了一个对象,改对象实现了注解类,该对象是注解的子类对象,
//该对象会复写注解的抽象方法,然后返回使用注解时传递的参数
Pro an = (Pro) ProTest1.getAnnotation(Pro.class);
3.调用注解中的抽象方法,获取注解中配置的属性值
@Pro(className = "cn.itcast.jdbc.show",methodName = "show")
public class ProTest1 {
public static void main(String[] args) throws Exception {
//1.解析注解
//2.获取该类的字节码文件对象
Class ProTest1 = ProTest1.class;
//3.获取注解对象
//其实就是在内存中创建了一个对象,改对象实现了注解类,该对象是注解的子类对象,
//该对象会复写注解的抽象方法,然后返回使用注解时传递的参数
Pro an = (Pro) ProTest1.getAnnotation(Pro.class);
//4.调用注解对象中定义的抽象方法,获取返回值
String className = an.className();
String methodName = an.methodName();
System.out.println(className);
//加载该类进内存
Class<?> aClass = Class.forName(className);
//创建对象
Object obj = aClass.newInstance();
//获取方法对象
Method method = aClass.getMethod(methodName);
//执行方法
method.invoke(obj);
}
}
注解使用的一个小案例
这个小案例是使用自定义注解@check,检测类的方法是否出现了异常,如果出现异常就打印到日志文件中显示出来
定义自定义注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface check {
}
定义测试类
public class test {
@check
public void add(){
System.out.println("d");
}
@check
public void add2(){
int a ;
a=1/0;
System.out.println(1/0);
}
}
定义执行框架
public class ceshi {
public static void main(String[] args) throws IOException {
//创建测试类的对象
test test = new test();
//获取到这个类的所有成员方法
Class aClass = test.getClass();
Method[] methods = aClass.getMethods();
int number =0;
//日志缓冲流
BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
//遍历所有方法,查找方法的上一行有么有@check
for (Method method : methods) {
//通过这一行判断
if (method.isAnnotationPresent(check.class)){
try {
method.invoke(test);
}catch (Exception e){
number++;
System.out.println(method.getName());
bw.write(method.getName()+"异常了");
bw.newLine();
bw.write("异常名称"+e.getCause().getClass());
bw.newLine();
bw.write("异常原因"+e.getCause());
bw.newLine();
}
}
}
bw.write("一共"+number+"异常");
//输出流刷新
bw.flush();
}
}
日志文件
add2异常了
异常名称class java.lang.ArithmeticException
异常原因java.lang.ArithmeticException: / by zero
一共1异常
小结:
1.以后我们大多都是学习怎么使用注解,而不是自己自定义注解
2.注解给谁用?
1.编译器
2.给解析程序使用
3.注解不是程序的一部分,可以理解注解是方法.类等的一个标签