国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > 综合技术 > 注解基础

注解基础

来源:程序员人生   发布时间:2017-03-06 11:08:02 阅读次数:3004次

注解系列

注解基础

APT

JavaPoet

0x00 概述

本文主要是介绍注解的基础知识,为后面的APT和JavaPoet打下基础

0x01 甚么是注解

注解(Annotation)是Java5的1个新特性,是插入在代码中的1种注释或说是1种元数据(meta data),这些注释信息可以在编译期使用预编译工具进行获得处理,也能够在运行期使用Java反射机制来获得,这取决于你的注解类型。

0x02 注解的语法及其定义

在Android中注解常常存在我们代码中:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);
        getIntentData();
    }

上面的@Override就是系统的注解,表明这是个重写方法,点击源码可以看到长成下面的模样

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Override {
    }

实际中会带有1些参数

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface run_methodInfo {
        String name() default "long";
        String data();
        int id() default 365;
    }

@Retention @Target @Document @Inherited4种 是元注解即 “注解的注解”

@Target 表示该注解目标,可能的 ElemenetType 参数包括:

  • ElemenetType.CONSTRUCTOR 构造器声明
  • ElemenetType.FIELD 域声明(包括 enum 实例)
  • ElemenetType.LOCAL_VARIABLE 局部变量声明
  • ElemenetType.METHOD 方法声明
  • ElemenetType.PACKAGE 包声明
  • ElemenetType.PARAMETER 参数声明
  • ElemenetType.TYPE 类,接口(包括注解类型)或enum声明

@Retention 表示该注解的生命周期,可选的 RetentionPolicy 参数包括

  • RetentionPolicy.SOURCE 注解只保存在源文件,当Java文件编译成class文件的时候,注解被抛弃注解将被编译器抛弃
  • RetentionPolicy.CLASS 注解被保存到class文件,但jvm加载class文件时候被抛弃
  • RetentionPolicy.RUNTIME 注解不但被保存到class文件中,jvm加载class文件以后,依然存在;,因此可以通过反射机制读取注解的信息

@Documented 唆使将此注解包括在 javadoc 中
@Inherited 唆使允许子类继承父类中的注解

使用注解需要遵照它的规则:

  • Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这1接口,并且不能再去继承别的类或是接口.
  • 参数成员只能用public或默许(default)这两个访问权修饰
  • 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean8种基本数据类型和String、Enum、Class、annotations等数据类型,和这1些类型的数组.
  • 要获得类方法和字段的注解信息,必须通过Java的反射技术来获得 Annotation对象,由于你除此以外没有别的获得注解对象的方法(分为编译期还是运行期)

0x03 使用

(这里仅介绍最多见的运行期的注解,编译期注解触及到apt、javapoet会单独再开1篇介绍)

Step One 定义注解

先看3个Runtime注解,包括类、方法、字段,

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface run_classInfo {
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface run_methodInfo {
    String name() default "long";
    String data();
    int id() default 365;
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface run_fieldInfo {
    int[] value();
}

Step two 使用这些注解,

@run_classInfo("类注解RunTime Class")
public class RunTimeTest {
    @run_fieldInfo(value = {77, 88})
    public String fieldInfo = "filedInfo";

    @run_fieldInfo(value = {163})
    public int id = 55;

    @run_methodInfo(name = "彩笔学长", data = "finance")
    public static String getMethod() {
        return RunTimeTest.class.getSimpleName();
    }
}

使用反射解析注解

    /**
     * 解析运行时注解
     */
    private void showRunTimeInfo() {
        StringBuffer sb = new StringBuffer();
        //获得Class 注解
        Class<?> clazz = RunTimeTest.class;
        Constructor<?>[] constructors = clazz.getConstructors();
        //获得包括的注解类信息
        run_classInfo runClassInfo = clazz.getAnnotation(run_classInfo.class);
        if (runClassInfo != null) {
            //获得class注解
            sb.append("Class注解: ").append("\n");
            sb.append(Modifier.toString(clazz.getModifiers())).append(" ")
                    .append(clazz.getSimpleName()).append("\n");

            sb.append("注解值:").append("\n")
                    .append(runClassInfo.value()).append("\n\n");
        }

        //获得Field注解
        sb.append("Field注解:").append("\n");
        Field[] fields = clazz.getDeclaredFields(); //获得本身的不包括继承类
        for (Field field : fields) {
            //获得field注解类信息
            run_fieldInfo fieldInfo = field.getAnnotation(run_fieldInfo.class);
            if (fieldInfo != null) {
                sb.append(Modifier.toString(field.getModifiers())).append(" ")
                        .append(field.getType().getSimpleName()).append(" ")
                        .append(field.getName()).append("\n");
                sb.append("注解值: ").append("\n")
                        .append(Arrays.toString(fieldInfo.value())).append("\n\n");
            }
        }

        //获得Method 注解
        sb.append("Method注解: ").append("\n");
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            run_methodInfo methodInfo = method.getAnnotation(run_methodInfo.class);
            if (methodInfo != null) {
                sb.append(Modifier.toString(method.getModifiers())).append(" ")
                        .append(method.getReturnType().getSimpleName()).append(" ")
                        .append(method.getName()).append("\n");
                sb.append("注解值:").append("\n");
                sb.append("name: ").append(methodInfo.name()).append("\n");
                sb.append("data: ").append(methodInfo.data()).append("\n");
                sb.append("id: ").append(methodInfo.id()).append("\n");
            }

        }
        tvDes.setText(sb.toString());
    }

0x04 参考文献

  • http://www.cnblogs.com/lbangel/p/3523741.html
  • http://blog.csdn.net/github_35180164/article/details/52107204
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生