注解
概念:说明程序的,给计算机看
注释:用文字描述程序
先了解一些怎么正常javadoc文档
1:给类或者方法添加doc注释
2:通过命令javadoc 执行 类.java文件
新建的类:
/*** 注解doc演示
*@authorquan
*@sincejdk 1.7
*@version1.8*/
public classAnnotation {/*** 计算两个数的和
*@parama 整数
*@paramb 整数
*@return两束的和*/
public int dd(int a,intb){return a+b;
}
}
快捷键:
在类的所在的文件夹里面
shift+右键就能在这个路径下打开命令行
执行命令
查看生成的api文件
JDK种预定义的一些注解
没加入SupperssWarning的时候:
会出现一些告警
自定义注解
格式
public @interface 注解名称
本质: 注解的本质就是一个接口,改接口默认继承Annotation接口
PS C:\Users\quan\Desktop\date>javac .\Myannotation.java
PS C:\Users\quan\Desktop\date> javap .\MyAnnotation.classCompiled from"Myannotation.java"
public interface MyAnnotation extendsjava.lang.annotation.Annotation {
}
属性:接口种可以定义的成员的方法
要求:
属性的只能返回值类型:基本数据类型 String 枚举 注解 以及他们的数组
定义了属性,在使用时需要给定属性的值
如果定义属性的时候,利用default关键字给定属性初始值,则使用注解时可以不赋值
如果只有一个属性需要赋值,并且属性名称时value,则value可以升序,直接定义值即可
数组赋值时,值使用大括号包裹,如果数组之哟一个值,大括号可以不写
枚举类:
public enumPersonE {
p1,p2,p3;
}
自定义注解:
public @interfaceMyAnnotation {//抽象方法
public String show() default "ALL";public intage();publicString[] str();publicPersonE p();
}
使用自定义注解:
@MyAnnotation(show = "quan",age = 12,str = {"quan","zhi"},p=PersonE.p1)public voiddemo(){
}
元注解
用于描述注解的注解:
Target
/*ElementType的取值
TYPE:可以作用类上
METHOD:可以作用方法上
FIELD:可以作用与成员变量上*/
@Target(value = {ElementType.TYPE,ElementType.FIELD})//表示该MyAnnoT注解只能作用与类上
public @interfaceMyAnnoT {
}
Retention
返回值时枚举类:
/*@Retention(RetentionPolicy.RUNTIME )当前白描述的注解,会保留到class字节码文件中国,并被JVM读取到*/
@Target(value = {ElementType.TYPE,ElementType.FIELD})//表示该MyAnnoT注解只能作用与类上
@Retention(RetentionPolicy.RUNTIME )public @interfaceMyAnnoT {
}
Documented
@Documented//表示,未来会集合到javadoc文档种
Inherited
@Inherited//表示是否会被继承
@Target(value = {ElementType.TYPE,ElementType.FIELD})//表示该MyAnnoT注解只能作用与类上
@Retention(RetentionPolicy.RUNTIME )
@Documented//表示,未来会集合到javadoc文档种
@Inherited//表示是否会被继承
public @interfaceMyAnnoT {
}
在程序中实际应用注解,解析注解
获取注解中定义中的属性值
定义一个注解:
/*** 描述需要执行的类名和方法名*/@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)public @interfacePro {
String className();
String methodName();
}/*public class ProImpl implements Pro{
String className(){
return "annotaion.Demo1";
}
String methodName(){
retun "show";
}
}
定义一个类:
packageannotaion;public classDemo1 {public voidshow(){
System.out.println("demo1..show...");
}
}
定义一个使用注解的累
@Pro(className = "annotaion.Demo1",methodName = "show")public classReflectTest {public static void main(String[] args) throwsException {/*不能改变框架的任何代码
可以创建任意类的对象,可以执行任意方法*/
//111解析注解:获取该类的字节码文件对象
Class reflectTestClass = ReflectTest.class;//222获取上边的注解//其实上面就是在内存中生成一个该注解接口子类实现对象
Pro an = reflectTestClass.getAnnotation(Pro.class);/*public class ProImpl implements Pro{
String className(){
return "annotaion.Demo1";
}
String methodName(){
retun "show";
}
}*/
//333调用注解对象中的抽象方法,获取放回值
String className =an.className();
String methodName=an.methodName();//利用Class的静态方法forName,传入全类名去获取指定类的Class对象
Class cls =Class.forName(className);
System.out.println(cls);//class annotaion.Demo1//通过Class对象的newInstance去实现无参实体类
Demo1 obj1 = (Demo1) cls.newInstance();//这里使用类的强制转换
obj1.show();
System.out.println(obj1);//annotaion.Demo1@61bbe9ba
Object obj= cls.newInstance();//因为这里使用Object接受,多态。
System.out.println(obj);//annotaion.Demo1@61bbe9ba//通过Class对象去获取类的方法
Method method =cls.getMethod(methodName);
System.out.println(method);//public void annotaion.Demo1.show()//执行方法,指定执行的实体类
method.invoke(obj);
}
}
re:
classannotaion.Demo1
demo1..show...
annotaion.Demo1@61bbe9ba
annotaion.Demo1@610455d6public voidannotaion.Demo1.show()
demo1..show...
计算器检测bug案例
需要测试下面这个计算器有没有bug
packageannotationDemo;public classCalulator {
@Checkpublic voidadd(){
String str= null;
str.toString();
System.out.println("1 + 0 = " +(1 + 0));
}
@Checkpublic voidsub(){
System.out.println("1 - 0 = " + (1 - 0));
}
@Checkpublic voidmul(){
System.out.println("1 * 0 = " + (1 * 0));
}
@Checkpublic voiddiv(){
System.out.println("1 / 0 = " + (1 / 0));
}public voidshow(){
System.out.println("no bug");
}
}
定义一个注解去实现:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)public @interfaceCheck {
}
程序中利用注解:
importjava.io.BufferedOutputStream;importjava.io.BufferedWriter;importjava.io.FileWriter;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;/*** 简单测试
* 主方法执行,会制动执行被加了注解的方法,判断方法是否有异常
* 将异常记录到文件当中*/
public classTestCheck {public static void main(String[] args) throwsIOException {//实体类
Calulator c = newCalulator();//2获取字节码文件对象
Class cls =c.getClass();//3获取所有方法
Method[] methods =cls.getMethods();int number = 0;//出现异常的次数//异常记录数据
BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));//4判断方法中是否有Check注释
for(Method method : methods) {if(method.isAnnotationPresent(Check.class)){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();
}
}
结果生成的bug.txt