zoukankan      html  css  js  c++  java
  • java 注解的使用和原理

    基本特性

    1、jdk 1.5之后才引入的。

    2、用来说明程序的。(注释是给程序员看的,注解就是给电脑看的)

    java注解的作用分类

    1、编写文档:通过代码标识的注解生成文档。【生成doc文档】

    2、代码分析:通过代码标识的注解对代码进行分析。【使用反射】

    3、编译检查:通过代码标识的注解让编译器能够实现基本的编译检查。【override】

    测试类:

    /**
     * 我的javadoc测试
     */
    public class TestCode {
        /**
         * 计算两个数的和
         * @param a 整数a
         * @param b 整数b
         * @return 返回两个数的和
         */
        public int add(int a, int b){
            return a+b;
        }
    }

    对于2、3两点我们应该是知道的。尽管可能不知道里面的原理。但是是平时都在用的。但是对于1点还可以生成doc文档

    测试操作如下:

    D:softjdkinjavadoc.exe .TestCode.java -encoding utf-8 -docEncoding utf-8 -charset utf-8

    生成了一大堆的东西:

    打开TestCode.html可以发现,我们的java api手册就是这样生产的。

    注解来源分类

    1、jdk自带的注解,如常见的override(重写校验),deprecated(表示弃用)

    2、自定义的注解

    1)格式, 以override为例:

           

     2)注解的本质

    我们编写一个简单的注解

    MyAnnotation.java

    public @interface MyAnnotation {
    }

    我们通过编译和反编译看下最终是什么样的结果:

    D:softjdkinjavac.exe MyAnnotation.java
    D:softjdkinjavap.exe MyAnnotation.class

    结果如下:

    public interface MyAnnotation extends java.lang.annotation.Annotation {


    }

    可以发现注解的本质就是接口,这个接口继承了jdk里面的Annotation接口。

    3)注解的属性

    由于注解本质为接口,那么里面可以定义未实现的方法。这些称为注解的“属性”。

    属性的返回类型有(返回值不能为void):

    • 基本数据类型
    • String
    • 枚举
    • 注解
    • 以及以上四种类型的数组

    例子:

    public enum Person {
        PS;
    }
    
    public @interface Annotation2 {
    }
    
    public @interface MyAnnotation {
        String stringValue();
        int integerValue();
        Person personValue();
        Annotation2 myAnnotationValue();
        String[] stringArrayValue();
    }

    属性的使用,需要注意几点:

    • 定义了属性在使用的时候就要给属性赋值,除非设置default值。如:String stringValue() default "aaa";
    • 如果属性为value且属性只有这一个,那么value可以省略,直接填写属性值。
    • 如果是数组,需要用{}包含起来。
    
    
    public @interface MyAnnotation {
    String stringValue() default "xxx";
    int integerValue();
    String[] stringArrayValue();
    }

    public @interface Annotation2 {
    String value();
    }

    @MyAnnotation(integerValue = 1, stringArrayValue = {"aaa", "bbb"})
    @Annotation2("default")
    public class TestCode {
    /**
    * 计算两个数的和
    * @param a 整数a
    * @param b 整数b
    * @return 返回两个数的和
    */
    public int add(int a, int b){
    return a+b;
    }

    @Override
    public String toString() {
    return super.toString();
    }
    }

    元注解

    元注解是你在编写注解的时候,上面加的注解,就是注解的注解。主要有4个。

    • @target, 用于指定注解的使用位置。如@Target(ElementType.ANNOTATION_TYPE),@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})。
    • @Inherited,表示父类加了这个注解,子类也自动加上。
    • @Documented, 表示这个注解的信息在执行javadoc的时候是否抽取到api文档中。
    • @Retention,表示注解被保留的阶段,java类,class文件,以及被jvm读取。总共三种。RetentionPolicy.SOURCE, RetentionPolicy.CLASS, RetentionPolicy.RUNTIME

    元注解的内容,可以到jdk源码里面看一下,更有利于理解。

    解析注解

    这个是最关键了,以上加了这么多的属性,并且还为这些属性附了值,那么是希望程序读取这些值,进行使用的。那其实就是要看如何拿到这些注解配置的值。

    测试:
    MyAnnotition.java:

    package annotation_;
    
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
        String stringValue() default "xxx";
        int integerValue();
    }

    TestCode.java:

    package annotation_;
    
    @MyAnnotation(integerValue = 1)
    public class TestCode {
        public static void main(String[] args) {
            Class<TestCode> testCodeClass = TestCode.class;
            MyAnnotation myAnnotation = testCodeClass.getAnnotation(MyAnnotation.class);
            int i = myAnnotation.integerValue();
            String s = myAnnotation.stringValue();
            System.out.printf("i = %d, s = %s
    ", i, s);
        }
    }

    输出结果:

    Connected to the target VM, address: '127.0.0.1:49586', transport: 'socket'
    i = 1, s = xxx
    Disconnected from the target VM, address: '127.0.0.1:49586', transport: 'socket'
    
    Process finished with exit code 0

    是不是感觉可以当配置文件使用。但是最主要的问题是myAnnotation.integerValue(), myAnnotation.stringValue()为什么可以拿到对应的值,这个也是最核心的问题。

    那就是getAnnotation里面返回了一个实现了MyAnnotation注解(注解的本质是接口)的实例。这个类大概是长这样的。

    package annotation_;
    
    import java.lang.annotation.Annotation;
    
    public class MyAnnotationImpl implements MyAnnotation{
        public String stringValue() {
            return "xxx";
        }
    
        public int integerValue() {
            return 0;
        }
    
        public Class<? extends Annotation> annotationType() {
            return null;
        }
    }

    所以就可以通过抽象方法获取到对应的值。(如何生成这样的一个类,只是学习注解,可以不关心。要不然,只能看里面的源码。因为如果自定义注解,你只会用到这一步,去获取值。)

  • 相关阅读:
    关于iframe页面里的重定向问题
    iframe跨域解决方案
    sql 查询优化小计
    年轻不能遇见太惊艳的人
    图片上传预览
    脚本
    前端常见跨域解决方案
    react
    react高阶组件
    React + MobX 状态管理入门及实例
  • 原文地址:https://www.cnblogs.com/chenmz1995/p/13049048.html
Copyright © 2011-2022 走看看