zoukankan      html  css  js  c++  java
  • java注解

    注解概念与注解的作用

    1. 注解定义:注解是一种元数据,是在jdk1.5以及以后的版本引入的,与类,接口,枚举在同一层次的,它可以声明在一个类,方法,属性等前面,用来对这些元素进行说明,解释。
    2. 注解的作用:
      • 编写文档:通过代码标识的注解,来生成文档(doc文档,api文档)
      • 代码分析:通过代码标识的注解,来对代码进行分析(反射)
      • 编译检查:通过代码标识的注解,来对代码进行编译前的检查(Override注解)

     注解的本质

      通过自定义一个注解AnnoDemo 里面含有一个name属性,然后对AnnoDemo的class文件进行反编译得到如下内容:

         

      从上面结果看出,AnnoDemo注解本质是一个继承java.lang.annotation.Annotation接口的一个接口,注解AnnoDemo属性name,本质上是一个抽象方法。具体自定义注解规则在下面自定义注解再将。

    自定义注解

    1. 自定义注解的语法:@interface 注 名{ 注解属性列表} 
    2. 属性和属性取值类型:属性就是指接口中的抽象方法:属性取值类型可以是八大基本类型,String类型,枚举类型,注解,以及上面三种类型的数组
    3. 注解使用:如果注解定义了属性,在使用时需要给属性赋值操作,有以下注意事项:如果定义属性时,用default 给属性一个默认值,那么使用注解时,可以不给属性赋值操作,如果注解只定义一个属性时,并且属性名为value,使用注解时,对属性赋值,可以省去属性名=,可以直接定义值。数组属性赋值操作规则为{值1,值2 ...}
    4. 自定义注解一般需要用到元注解,元注解指的是描述注解的注解,在下面会介绍jdk的四大元注解:

    jdk四大元注解

    • @Target:注解作用的位置
    • @Retention:注解的生命周期
    • @Documented:注解是否应当被包含在 JavaDoc (api)文档中
    • @Inherited:是否允许子类继承该注解

    其中,@Target 指的是注解是作用在类上,还是方法,属性上。@Target注解定义如下:

     通过ElementType 这个枚举类型的值,指定作用的位置,ElementType有以下一些值:

    • ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
    • ElementType.FIELD:允许作用在属性字段上
    • ElementType.METHOD:允许作用在方法上
    • ElementType.PARAMETER:允许作用在方法参数上
    • ElementType.CONSTRUCTOR:允许作用在构造器上
    • ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
    • ElementType.ANNOTATION_TYPE:允许作用在注解上
    • ElementType.PACKAGE:允许作用在包上

    @Retention 用于指明当前注解的生命周期,定义如下:

    通过 RetentionPolicy 这个枚举类型的值,指定注解的生命周期,RetentionPolicy有以下取值:

    • RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件
    • RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件
    • RetentionPolicy.RUNTIME:永久保存,可以反射获取

    @Retention 注解指定了被修饰的注解的生命周期,一种是只能在编译期可见,编译后会被丢弃,一种会被编译器编译进 class 文件中,无论是类或是方法,乃至字段,他们都是有属性表的,而 JAVA 虚拟机也定义了几种注解属性表用于存储注解信息,但是这种可见性不能带到方法区,类加载时会予以丢弃,最后一种则是永久存在的可见性。

    剩下两种类型的注解我们日常用的不多,也比较简单,这里不再详细的进行介绍了,你只需要知道他们各自的作用即可。@Documented 注解修饰的注解,当我们执行 JavaDoc 文档打包时会被保存进 doc 文档,反之将在打包时丢弃。@Inherited 注解修饰的注解是具有可继承性的,也就说我们的注解修饰了一个类,而该类的子类将自动继承父类的该注解。

    常用的java内置注解

    • @Override:  该注解标注的方法必须继承父类(接口),否则编译不通过。该注解定义如下:

         

    • @Deprecated: 该注解标注的代码(方法),表示这些代码已经过时了,该注解定义如下:

          

    • @SuppressWarinings:该注解标注的代码,如果有警告,会压制警告。使用该注解时,一般给value属性赋值all,该注解定义如下:

          

     注解案例

    •  自定义一个StudentAnno注解代码如下:
         
    //自定义枚举类型AnnoStudent
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface AnnoStudent {
        int age();
        String name();
        String [] course();
        Target anno();
        Grade grade();
    }
    //枚举类Grade
    public enum Grade {
      SMALL,MID,HIGH;
    }
    //测试类
    @AnnoStudent(age=15,name="jack",course={"Enlish","Math"},anno = @Target(ElementType.ANNOTATION_TYPE),grade=Grade.HIGH
    )
    public class TestAnno {
        
    }
    •  定义一个检测注解,检测一个Calculator类的所有方法是否正常运行,如果异常将其记录在一个log文件中,该过程结合了反射:具体代码如下:
    //注解类
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface CheckAnno {
    }
    //如果检测的类
    /**
     * 模拟一个计算器类
     */
    public class Calculator {
        //加法
        @CheckAnno
        public void add(){
            System.out.println("1+0="+(1+0));
        }
        //减法
        @CheckAnno
        public void sub(){
            System.out.println("1-0="+(1-0));
        }
        //乘法
        @CheckAnno
        public void multi(){
            System.out.println("1*0="+(1*0));
        }
        //除法
        @CheckAnno
        public void div(){
            System.out.println("1/0="+(1/0));
        }
    }
    
    /**
     *检查计算器类方法是否正常运行,如果不正常运行的方法,将异常的方法,异常的名称,异常的原因记录在checkLog文件中
     */
    public class TestCheck {
        public static void main(String[] args )throws IOException {
            Calculator c=new Calculator();
            //获取计算类的字节码
            Class cla =c.getClass();
            //获取计算器类的所有定义的方法
           Method [] methodss= cla.getDeclaredMethods();
           int num=0;//出现异常的方法数
            BufferedWriter bw=new BufferedWriter(new FileWriter("checkLog.txt"));
           for(Method method:methodss){
               //判断当前方法是否使用Check注解
               if( method.isAnnotationPresent(CheckAnno.class)){
                   try{
                       //调用计算器的方法
                       method.invoke(c);
                   } catch(Exception e) {
                        //异常处理
                       bw.write("出现异常的方法:"+method.getName());
                       bw.newLine();
                       bw.write("异常的名称:"+e.getCause().getClass().getSimpleName());
                       bw.newLine();
                       bw.write("异常的原因:"+e.getCause().getMessage());
                       bw.newLine();
                       num++;
                   }
    
    
               }
    
           }
           bw.write("调用该方法一共出了"+num+"次异常");
            bw.close();
    
    
    
    
        }
    }
    • 注解与反射结合,获取任意类的对象,调用对象的任意方法,注解相当于配置文件的左右,代码如下:
    //注解
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ReflectAnno {
        String className();
        String classMethod();
    
    }
    //测试注解与反射的类
    /**
     * 注解与反射结合,获取任意类的对象,并调用该对象的任意方法
     * 注解相当与配置文件
     */
    @ReflectAnno(className = "cn.ck.annotation.Student",classMethod = "show")
    public class ReflectTest {
        public static void main(String[] args) throws Exception {
            //获取相应的注解对象
            ReflectAnno ra= ReflectTest.class.getAnnotation(ReflectAnno.class);
           //注解对象调用相应的抽象方法获取classname属性值,classMethod属性值
           String classMethod= ra.classMethod();
           String className=ra.className();
           //将类加载进内存
           Class cla= Class.forName(className);
           //创建对象
           Object obj=cla.newInstance();
           //通过classMethod值,获取相应的方法
            Method method=cla.getDeclaredMethod(classMethod);
            //调用方法
            method.invoke(obj);
    
    
        }
    }

    Class 类中提供了以下一些方法用于反射注解。

    • getAnnotation:返回指定的注解
    • isAnnotationPresent:判定当前元素是否被指定注解修饰
    • getAnnotations:返回所有的注解
    • getDeclaredAnnotation:返回本元素的指定注解
    • getDeclaredAnnotations:返回本元素的所有注解,不包含父类继承而来的
  • 相关阅读:
    loadrunner提高篇
    loadrunner提高篇
    loadrunner提高篇
    STM32F4XX高效驱动篇1-UART
    系统封装接口层 cmsis_os
    uCGUI 按键窗口切换机制
    xming+xshell让linux变成桌面化操作
    jmeter做WebSocket请求解读
    性能监控工具spotlight操作
    linux性能监控命令,磁盘,网络,cpu,内存
  • 原文地址:https://www.cnblogs.com/shareAndStudy/p/12730723.html
Copyright © 2011-2022 走看看