JAVA自定义注解,java自定义注解怎么生效的

  JAVA自定义注解,java自定义注解怎么生效的

  00-1010概念函数JDK注释中预定义的一些注释生成文档用例自定义注释格式本质属性:接口元注释中的抽象方法:用于描述注释的注释用于程序(解析)注释:获取注释用例中定义的属性值:通过自定义注释定义一个简单的测试框架摘要。

  00-1010概念:解释程序。为了电脑。

  注释:用文字描述程序。对于程序员来说。

  定义:注释,也称为元数据。代码级别的描述。是JDK1.5及以后版本引入的特性,和类、接口、枚举是一个级别的。可以在包、类、字段、方法、局部变量、方法参数等前面声明。来解释和评论这些元素。

  00-1010功能分类:

  写文档:通过代码中标识的注释生成文档【生成文档doc文档】代码分析:通过代码中标识的注释分析代码【使用反射】编译检查:通过代码中标识的注释使编译器实现基本编译检查【覆盖】。

  

目录

@Override:检查此注释标记的方法是否继承自父类(接口)

 

  @Deprecated:此评论标记的内容表示已经过时。

  @SuppressWarnings:取消警告

  传递常规参数all @SuppressWarnings(all )

  00-1010 api类案例生成doc文档:

  /* * * Note javadoc demo * * @ AuthorZJQ * @ version 1.0 * @ since 1.5 */public class annodoc {/* * *计算两个数之和* @ param a integer * @ param b integer * @ return两个数之和*/public int add (int a,int b){ return a b;}}在相应的类目录中输入cmd并执行以下命令

  执行JavaDoc AnnoDoc.java后,可以看到已经生成了很多html、js等前端文件。单击index.html。您可以看到以下效果:

  

概念

 

  00-1010元标注public @interface标注名称{属性列表;}

  00-1010 Annotation本质上是一个接口,默认继承Annotation接口。

  公共接口MyAnno扩展Java . lang . annotation . annotation { }

  00-1010要求:

  1.属性的返回值类型具有以下值

  基本数据类型

  线

  列举

  给…作注解

  以上类型的数组

  2.定义了属性,使用时需要赋值。

  如果default关键字用于在定义属性时初始化属性的默认值,则可以不带注释地分配属性。如果只需要分配一个属性,并且属性的名称是value,那么可以省略value,直接定义value。分配数组时,该值用{}包装。如果数组中只有一个值,{}可以省略这种情况:

  定义

  public @ interface MyAnno { int value();每人();myanno 2 anno 2();string[]strs();}公共枚举人{ P1,P2;}使用

  @MyAnno(值=12,每人=人。P1,anno2=@MyAnno2,strs=bbb )公共类Worker { }

  00-1010@Target:描述了注释可以工作的位置。

  ElementType值:类型:可以作用于类;方法:可以作用于

  方法上FIELD:可以作用于成员变量上@Retention:描述注解被保留的阶段

  @Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到,自定义注解一般用这个。

  @Documented:描述注解是否被抽取到api文档中

  @Inherited:描述注解是否被子类继承

  

 

  

在程序使用(解析)注解:获取注解中定义的属性值

之前我们在反射中有通过读取配置文件来创建任意类的对象,执行任意方法。具体反射内容可以看我的这篇文章:Java框架设计灵魂之反射的示例详解

 

  之前反射中我们通过读取对应的配置文件然后创建类和执行方法,代码如下:

  

/**前提:不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法*/ //1.加载配置文件//1.1创建Properties对象Properties pro = new Properties();//1.2加载配置文件,转换为一个集合//1.2.1获取class目录下的配置文件ClassLoader classLoader = ReflectTest.class.getClassLoader();InputStream is = classLoader.getResourceAsStream("pro.properties");pro.load(is); //2.获取配置文件中定义的数据String className = pro.getProperty("className");String methodName = pro.getProperty("methodName"); //3.加载该类进内存Class cls = Class.forName(className);//4.创建对象Object obj = cls.newInstance();//5.获取方法对象Method method = cls.getMethod(methodName);//6.执行方法method.invoke(obj);

我们可以通过注解替换上述读取配置文件相关操作。具体代码如下:

 

  注解定义如下:

  

/** * 描述需要执行的类名,和方法名 * @author zjq */ @Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface Pro { String className(); String methodName();}

通过解析注解配置,执行相关对象创建和执行对象方法。

 

  获取注解定义的位置的对象 (Class,Method,Field)获取指定的注解调用注解中的抽象方法获取配置的属性值代码如下:

  

@Pro(className = "com.zjq.javabase.base25.annotation.Demo1",methodName = "show")public class ReflectTest { public static void main(String[] args) throws Exception { /** * 前提:不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法 */ //1.解析注解 //1.1获取该类的字节码文件对象 Class<ReflectTest> reflectTestClass = ReflectTest.class; //2.获取上边的注解对象 //其实就是在内存中生成了一个该注解接口的子类实现对象 /* public class ProImpl implements Pro{ public String className(){ return "com.zjq.javabase.base25.annotation.Demo1"; } public String methodName(){ return "show"; } } */ Pro an = reflectTestClass.getAnnotation(Pro.class); //3.调用注解对象中定义的抽象方法,获取返回值 String className = an.className(); String methodName = an.methodName(); System.out.println(className); System.out.println(methodName); //4.加载该类进内存 Class cls = Class.forName(className); //5.创建对象 Object obj = cls.newInstance(); //6.获取方法对象 Method method = cls.getMethod(methodName); //7.执行方法 method.invoke(obj); }}

 

  

案例:通过自定义注解定义一个简单的测试框架

定义一个测试注解

 

  

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface Check {}

定义一个计算器工具类,并在方法上使用@Check注解

 

  

/** * 小明定义的计算器类 * @author zjq */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..."); } }

定义测试框架类并执行测试,把测试异常记录到bug.txt文件中,代码如下:

 

  

/** * 简单的测试框架 * 当主方法执行后,会自动自行被检测的所有方法(加了Check注解的方法),判断方法是否有异常, * 记录到文件中 * * @author zjq */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(); } }

执行测试后可以在src同级目录查看到bug.txt文件内容如下:

 

  

add 方法出异常了异常的名称:NullPointerException异常的原因:null--------------------------div 方法出异常了异常的名称:ArithmeticException异常的原因:/ by zero--------------------------本次测试一共出现 2 次异常

 

  

 

  

总结

1.大多数时候,我们只是使用注解,而不是自定义注解。

 

  2.注解不是程序的一部分,可以理解为注解就是一个标签。

  3.注解给谁用?

  编译器

  给解析程序用

  到此这篇关于详解Java如何实现自定义注解的文章就介绍到这了,更多相关Java自定义注解内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: