java注解

注解

  • 定义:jdk1.5出现的新特性,与类,接口,枚举属同一层级,可用于包,类,属性,方法,方法参数前用于说明这些元素。
作用分类
  • 1、编写文档(注解标识 Javadoc生成文档)
    javadoc 类名.java 可根据注解注释得出文档
  • 2、代码分析(通过反射,分析注解标注的地方)
  • 3、编译检查(代码里标识的注解让编译器能够实现基本的编译检查)
预定义注解
  • 1.@Override 保证重写了父类的方法
  • 2.@Deprecated 已过时
  • 3.@SuppressWarnings(”all“) 压制警告
  • 4.@SafeVarargs 压制堆污染(使用有泛型的接收没泛型的)
  • 5.@FunctionalInterface 声明该接口是一个函数式接口(里面的抽象方法只有一个)
自定义注解
  • 注解的定义分两部分

    • 1、元注解
    • 2、public @Interface 注解名{}
  • 注解的真实面目:本质上是一个接口
    先编译,再反编译可知默认继承自java.lang.annotation.Annotation接口
    $ javap AnnoDemo.class
    Compiled from “AnnoDemo.java”
    public interface com.zengqifeng.rocketmqconsumer.annotation.AnnoDemo extends java.lang.annotation.Annotation {
    }

  • 注解的属性(即接口中声明的方法,故定义方法名时最好使用属性名,更易理解)

    • 要求:
    • 1、属性的返回值类型只能为如下几种
      • 基本数据类型
      • String类型
      • 枚举
      • 注解
      • 以上类型的数组
    • 2、定义了属性,在使用注解时需要给属性赋值
      • 1、定义属性时可以使用default关键字设置属性默认值
      • 2、如果注解只有一个属性需要赋值,并且属性名是value,赋值时可省略名字,直接写值
      • 3、数组类型属性赋值使用{},如果数组里只有一个值,{}可以省略
  • 元注解(用于描述注解的注解)

    • @Target({ElementType.METHOD, ElementType.TYPE})
      • 描述注解作用目标,属性是数组类型,使用{}包裹,如果只有一个,{}可以省略,作用目标可以使类,接口,枚举,方法,属性,方法参数
    • @Retention(RetentionPolicy.RUNTIME)
      • 注解被保留的阶段(source,class,runtime);当前注解(runtime)会保留到class文件中,并被jvm读取到内存。相比(class )应该是指挥被保留到class文件中,而不会被jvm读取到内存。推测source只会保留在源码阶段。
    • @Documented
      • Javadoc生成文档时,注解是否被抽取生成在文档中
    • @Inherited
      • 该注解标注的目标的子孙也继承该注解
在程序中解析注解(获取注解中定义的属性值)
  • 1、获取注解所在位置的对象
    • class,interface,enum,annotation,method,field,parameter等类型上
  • 2、获取注解(会生成该注解接口的实现类的对象)
  • 3、调用方法获取注解的属性值(实际上是上方生成的对象调用方法获取属性值)
package com.zengqifeng.rocketmqconsumer.annotation;

import java.lang.reflect.Method;

/**
 * @author zengqifeng
 * @version 1.0
 * @date 2019/12/26 14:39
 */
@AnnotationTest(className = "com.zengqifeng.rocketmqconsumer.annotation.TestDemo01", methodName = "show")
public class AnnotationTestDemo {
    public static void main(String[] args) throws Exception {
        //1、获取注解目标的字节码文件对象
        Class<AnnotationTestDemo> annotationTestDemoClass = AnnotationTestDemo.class;
        //2、获取注解对象
            //此处在内存中生成了该注解接口子类的对象
        AnnotationTest annotation = annotationTestDemoClass.getAnnotation(AnnotationTest.class);

        //3、获取注解上的属性值
        String className = annotation.className();
        String methodName = annotation.methodName();

        System.out.println(className);
        System.out.println(methodName);

        //拿到了className和methodName   反射调用任意对象的任意方法
        //1、获取calss对象
        Class cls = Class.forName(className);
        //2、获取构造方法 构造对象(如果单纯只需要无参构造方法,直接cls.newInstance即可)
        Object instance = cls.newInstance();
        //3、获取方法Method对象
        Method show = cls.getMethod("show");
        //4、方法调用
        show.invoke(instance);
    }
}

  • 注解和反射实现 自动检测类中标注有Check注解的所有方法,并返回测试报告
package com.zengqifeng.rocketmqconsumer.annotation;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author zengqifeng
 * @version 1.0
 * @date 2019/12/26 15:44
 */
public class TestDemo {

    //加减乘除法的测试
    static int a = 1,b = 0;

    @Check
    public void add() {
        System.out.println("1 + 0=" + (a+b) );
    }
    @Check
    public void del() {
        System.out.println("1 - 0=" + (a-b) );
    }
    @Check
    public void mul() {
        System.out.println("1 * 0=" + (a*b) );
    }
    @Check
    public void div() {
        System.out.println("1 / 0=" + (a/b) );
    }

    public void show() {
        System.out.println("没加Check注解,不会被执行,检测不出bug");
    }


    public static void main(String[] args) throws IOException {
        //测试所有Check注解标注的方法    给出测试报告
        //1、获取类的Class对象
        TestDemo testDemo = new TestDemo();
        Class testDemoClass = testDemo.getClass();
        //2、获取所有方法(此处获取的是所有的public修饰的方法)
        Method[] methods = testDemoClass.getMethods();
        int number = 0;
        //3、如果方法上有Check注解,那么执行
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("bug.txt"));
        for (Method method : methods) {
            if (method.isAnnotationPresent(Check.class)) {

                try {
                    method.invoke(testDemo);
                } catch (Exception e) {
                    //4、如果发生异常,捕获异常,记录在文件中
                    number ++;
                    bufferedWriter.write(method.getName() + "方法出现异常");
                    bufferedWriter.newLine();
                    bufferedWriter.write("异常类型:" + e.getCause().getClass().getSimpleName());
                    bufferedWriter.newLine();
                    bufferedWriter.write("异常原因:" + e.getCause());
                    bufferedWriter.newLine();
                    bufferedWriter.write("---------------");
                    bufferedWriter.newLine();
                }
            }
        }
        bufferedWriter.write("本次测试出现异常次数:" + number);
        bufferedWriter.newLine();
        bufferedWriter.flush();
    }
}

  • bug.txt 文件内容
div方法出现异常
异常类型:ArithmeticException
异常原因:java.lang.ArithmeticException: / by zero
---------------
本次测试出现异常次数:1
  • 小结
    • 1、以后大多数时候,我们使用注解,而非写注解
    • 2、注解被谁使用
      • 1、编译器
      • 2、解析程序
    • 3、注解不属于程序的一部分,只是一种标注(辅助方案)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值