注解使用入门(一)

注解使用入门(一)


本篇博客要讲解主要分为以下几个问题

  1. 注解的相关知识点
  2. 基于运行时的注解的例子解析说明

至于关于编译时的注解,待下篇博客的时候会结合例子讲解一下,目前我也正在学习当中

注解的相关知识点

提到注解,大多数人应该都不默认,在我们程序中见到的@Override,@Deprected,@SupressWarnings等等,这些都是注解,只不过是系统自己封装好的,而我们平时比较少去深入理解是怎样实现的?

1)什么是注解(Annotation):

Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。

2)注解的分类:

根据注解参数的个数,我们可以将注解分为三类:
1. 标记注解:一个没有成员定义的Annotation类型被称为标记注解。这种Annotation类型仅使用自身的存在与否来为我们提供信息。比如后面的系统注解@Override;
2. 单值注解
3. 完整注解 

根据注解使用方法和用途,我们可以将Annotation分为三类:
1. JDK内置系统注解
2. 元注解
3. 自定义注解

3)元注解:

元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它annotation类型作说明。Java5.0定义的元注解:
1. @Target,
2. @Retention,
3. @Documented,
4. @Inherited

4)元注解解析说明

  • @Documented 是否会保存到 Javadoc 文档中

  • @Retention 保留时间,可选值

    SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS,SOURCE 大都为 Mark Annotation,这类 Annotation 大都用来校验,比如 Override, SuppressWarnings

  • @Target 可以用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等,未标注则表示可修饰所有

    ANONOTATION_TYPE(注解类型声明),
    PACKAGE(包)
    TYPE (类,包括enum及接口,注解类型)
    METHOD (方法)
    CONSTRUCTOR (构造方法)
    FIFLD (成员变量)
    PARAMATER (参数)
    LOCAL_VARIABLE (局部 变量)

  • @Inherited 是否可以被继承,默认为 false

5)什么是metadata(元数据):

元数据从metadata一词译来,就是“关于数据的数据”的意思。
 
 元数据的功能作用有很多,比如:你可能用过Javadoc的注释自动生成文档。这就是元数据功能的一种。总的来说,元数据可以用来创建文档,跟踪代码的依赖性,执行编译时格式检查,代替已有的配置文件。如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:
1. 编写文档:通过代码里标识的元数据生成文档
2. 代码分析:通过代码里标识的元数据对代码进行分析
3. 编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查

其他知识点暂时不介绍,个人觉得一下子介绍太多概念很难消化。下面让我们一起结合例子来使用它。


下面我们来看一下我们要怎样写一个基于编译时的自定义注解的例子

自定义注解大概可分为以下三个步骤:
1. 自定义一个注解
2. 在其他类使用我们的注解
3. 在运行的时候解析我们的注解

解析运行流程图

1)首先我们我们来看一下我们是怎样自定义一个注解的

这些类型和它们所支持的类在java.lang.annotation包中可以找到。

/* 
 * 定义注解 MethodInfo 
 * 为方便测试:注解目标为类 方法,属性及构造方法 
 * 注解中含有三个元素 id ,name和 gid; 
 * id 元素 有默认值 0
 */ 

@Documented 
@Target({ElementType.TYPE,ElementType.METHOD,
    ElementType.FIELD,ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MethodInfo {
    String name() default "xujunTest";
    int id() default 0;
    Class<Long> gid();
}

解析说明

  • (1). 通过 @interface 定义,注解名即为自定义注解名,这里注解名为MethodInfo
  • (2). 注解配置参数名为注解类的方法名,且:

    a. 所有方法没有方法体,没有参数没有修饰符,实际只允许 public & abstract 修饰符,默认为 public,不允许抛异常

    b. 方法返回值只能是基本类型,String, Class, annotation, enumeration 或者是他们的一维数组

    c. 若只有一个默认属性,可直接用 value() 函数。一个属性都没有表示该 Annotation 为 Mark Annotation

  • (3). 可以加 default 表示默认值,如
String name() default "xujunTest";

2)接着我们来看一下我们要怎样使用我们自定义的注解

/**
 * 这个类专门用来测试注解使用
 * @author xujun
 */
 //类成员注解
@TestA(name="type",gid=Long.class) 
public class UserAnnotation {
    //类成员注解
    @TestA(name="param",id=1,gid=Long.class) 
    private Integer age;

    //构造方法注解
    @TestA (name="construct",id=2,gid=Long.class)
    public UserAnnotation(){

    }

    //类方法注解
    @TestA(name="public method",id=3,gid=Long.class)      
    public void a(){
        Map<String,String> m = new HashMap<String,String>(0);
    }

    //类方法注解
    @TestA(name="protected method",id=4,gid=Long.class) 
    protected void b(){
        Map<String,String> m = new HashMap<String,String>(0);
    }

    //类方法注解
    @TestA(name="private method",id=5,gid=Long.class) 
    private void c(){
        Map<String,String> m = new HashMap<String,String>(0);
    }

    public void b(Integer a){ 

    }
}

3)最后我们一起来看一下我们怎样在运行的时候解析我们的Annotation注解

运行时 Annotation 解析

(1) 运行时 Annotation 指 @Retention 为 RUNTIME 的 Annotation,可手动调用下面常用 API 解析

method.getAnnotation(AnnotationName.class);
method.getAnnotations();
method.isAnnotationPresent(AnnotationName.class);

其他 @Target 如 Field,Class 方法类似

  • getAnnotation(AnnotationName.class) 表示得到该 Target 某个 Annotation 的信息,因为一个 Target 可以被多个 Annotation 修饰
/*
* 根据注解类型返回方法的指定类型注解
*/
MethodInfo annotation = (MethodInfo) constructor
                     .getAnnotation(MethodInfo.class);
  • getAnnotations() 则表示得到该 Target 所有 Annotation
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
    MethodInfo methodInfo = (MethodInfo) annotation
}
  • isAnnotationPresent(AnnotationName.class) 表示该 Target 是否被某个 Annotation 修饰
/*
* 判断构造方法中是否有指定注解类型的注解
*/
boolean hasAnnotation = constructor
.isAnnotationPresent(MethodInfo.class);
if (hasAnnotation) {
    /*
    * 根据注解类型返回方法的指定类型注解
    */
    MethodInfo annotation = (MethodInfo) constructor
    .getAnnotation(MethodInfo.class);
}

测试代码

public class ParseAnnotation {

    static String className="com.xujun.animation.test.UserAnnotation";
    /**
     * 简单打印出UserAnnotation 类中所使用到的类注解 该方法只打印了 Type 类型的注解
     * 
     * @throws ClassNotFoundException
     */
    public static void parseTypeAnnotation() throws ClassNotFoundException {
        Class clazz = Class.forName(className);

        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            MethodInfo testA = (MethodInfo) annotation;
            System.out.println("id= \"" + testA.id() + "\"; name= \""
                    + testA.name() + "\"; gid = " + testA.gid());
        }
    }

    /**
     * 简单打印出UserAnnotation 类中所使用到的方法注解 该方法只打印了 Method 类型的注解
     * 
     * @throws ClassNotFoundException
     */
    public static void parseMethodAnnotation() {
        Method[] methods = UserAnnotation.class.getDeclaredMethods();
        for (Method method : methods) {
            /*
             * 判断方法中是否有指定注解类型的注解
             */
            boolean hasAnnotation = method.isAnnotationPresent(MethodInfo.class);
            if (hasAnnotation) {
                /*
                 * 根据注解类型返回方法的指定类型注解
                 */
                MethodInfo annotation = method.getAnnotation(MethodInfo.class);
                System.out.println("method = " + method.getName() + " ; id = "
                        + annotation.id() + " ; description = "
                        + annotation.name() + "; gid= " + annotation.gid());
            }
        }
    }

    /**
     * 简单打印出UserAnnotation 类中所使用到的方法注解 该方法只打印了 Method 类型的注解
     * 
     * @throws ClassNotFoundException
     */
    public static void parseConstructAnnotation() {
        Constructor[] constructors = UserAnnotation.class.getConstructors();
        for (Constructor constructor : constructors) {
            /*
             * 判断构造方法中是否有指定注解类型的注解
             */
            boolean hasAnnotation = constructor
                    .isAnnotationPresent(MethodInfo.class);
            if (hasAnnotation) {
                /*
                 * 根据注解类型返回方法的指定类型注解
                 */
                MethodInfo annotation = (MethodInfo) constructor
                        .getAnnotation(MethodInfo.class);
                System.out.println("constructor = " + constructor.getName()
                        + " ; id = " + annotation.id() + " ; description = "
                        + annotation.name() + "; gid= " + annotation.gid());
            }
        }
    }

    public static void main(String[] args) throws ClassNotFoundException {
        parseTypeAnnotation();
        parseMethodAnnotation();
        parseConstructAnnotation();
    }
}

运行以上测试程序,将可以看到以下输出结果

id= “0”; name= “type”; gid = class java.lang.Long
method = c ; id = 5 ; description = private method; gid= class java.lang.Long
method = b ; id = 4 ; description = protected method; gid= class java.lang.Long
method = a ; id = 3 ; description = public method; gid= class java.lang.Long
constructor = com.xujun.animationdemo.UserAnnotation ; id = 2 ; description = construct; gid= class java.lang.Long


转载请注明原博客地址: http://blog.csdn.net/gdutxiaoxu/article/details/52017033#t3

源码下载地址: http://download.csdn.net/detail/gdutxiaoxu/9582827

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。

android-----我眼中的Binder - 2016-07-25 18:07:17

        Binder作为进程间通信方式(IPC)的一种,算Android中比较难理解的部分了,今天计划以自己所认识的framework层的Binder原理来做个总结,好了,我们开始吧!         Android中利用Binder通信,首先肯定需要获得Binder对象了,但是系统服务和我们自定义服务Binder对象的获取方式是不一样的,原因就在于系统服务是在系统启动的时候被注册到ServiceManegr的,我们只需要通过ServiceManager.getService(String nam
使用xml作为数据交互的载体是Android中非常重要的功能,比如天气预报数据、短信备份数据、通讯录数据都可以以xml的格式通过网络传输。 为了演示Xml数据的操作,我模拟了一个短信备份的案例。 需求:界面如图1-10所示。上面是三个Button,前两个分别对应两种不同方式生成xml,第三个Button点击后解析备份的xml文件,然后将数据展现在下面的ScrollView中。短信数据是模拟的假数据。 生成的xml格式如文件1-10。 【文件1-10】 xml文件格式 1. ?xml version="1.
这篇博客我们来介绍一下责任链模式(Chain-of-responsibility Pattern),责任联模式又称为职责链模式,是 行为型设计模式 之一。顾名思义,责任链模式中存在一个链式结构,多个节点首尾相连,每个节点都可以被拆开再连接,因此,链式结构具有很好的灵活性。将这样一种结构应用于编程领域,将每一个节点看作是一个对象,每一个对象拥有不同的处理逻辑,将一个请求从链式的首段发出,沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止,这就是责任链或者职责链的通俗定义。 转载请注明出处: h

GeekBand第十一周笔记 - 2016-07-25 17:07:19

本周的主要内容介绍Gradle,NDK,管理依赖和Git等 一、Gradle Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。 面向Java应用为主。当前其支持的语言限于Java、Groovy和Scala,计划未来将支持更多的语言。 Coding只是软件开发中的一个部分 编译源代码 运行单元测试和集成测试 执行静态代码分析,生成分析报告 创建分布版本 部署到目标环
在安卓开发中,谷歌已经为我们提供了许多原生控件,基本上能够满足我们日常的开发需求,但是某些项目中原生控件可能达不到产品所要求的各式各样的酷炫效果或功能效果,这个时候我们只能自己自定义控件来满足项目需求,我们知道自定义控件包括三种方式: 1继承控件,即继承谷歌提供的原生控件,在此基础上提供一些原生控件不具备的功能,如github上各种酷炫效果的开源组件基本上都是采用的这种方式. 2组合控件:即组合多个原生控件来达到某些单个原生控件原本不具备的功能,这个在日常开发中应该是使用的比较多的,如基本上每个App都存

Android多点触摸交互处理 - 2016-07-25 17:07:15

安卓手机中,多点触摸是是最基本的操作,下面就使用程序进行演示多点触摸操作 一、获取触摸事件中的点击,移动和抬起事件,创建新的安卓项目,如下面代码所示,分别为MainActivity类代码和Layout布局文件,用于实现获取点击事件 1.1、MainActivity类中代码,代码中为布局对象root添加监听事件,使用switch进行对屏幕时间进行判断,用于判断事件的按下还是移动,在代码中      root=(RelativeLayout) findViewById(R.id.content);用于绑定布局
内容是博主照着书敲出来的,博主码字挺辛苦的,转载请注明出处,后序内容陆续会码出。 前言:ListView——列表,它作为一个非常重要的显示方式,不管是在Web中还是移动平台中,都是一个非常好的、不开或缺的展示信息的工具。在Android中,ListView控件接管了这一重担,在大量的场合下,我们都需要使用这个控件。虽然在Android 5.X时代,RecyclerView在很多地方都在逐渐取代ListView,但ListView的使用范围依然非常的广泛,它这万年老大哥的地位也不是轻易就能撼动的。下面就介绍
Android ListView使用简介 ListView 是 Android 软件开发中十分常用也十分重要的一个 UI 控件。 ListView 的每一个子项可以是一个简单的字符串,也可以是一组 View 的组合,开发者完全可以根据自己的需求来定义显示的形式。 如何使用一个 ListView 实现对数据的显示呢 ? 1. 创建 ListView 控件,已备数据显示 2. 准备要显示的数据 3. 为 ListView 构建一个数据适配器 (Adapter) 4. 绑定适配器 5. 处理 ListView
转载请标明出处: 一片枫叶的专栏 文本我们将讲解android studio打包apk,aar,jar包的相关知识。apk包就是android系统的安装包,这里没什么好说的,aar包是android中独有的类库包,而jar包是java中特有的类库包,在具体的介绍打包之前,我们先来aar包和jar包的区别。 jar包与aar包的区别 jar是java字节码文件(class文件)的归档文件,其不包含android中的资源文件等信息; aar是android中特有的归档文件,既包含字节码文件也包含android
欢迎转载,转载请注明出处: http://blog.csdn.net/dmk877/article/details/51980734 在上一篇文章中,我们详细讨论了Tween动画的xml的实现以及interpolator的使用,相信通过上篇文章大家对Tween动画的xml属性的配置会有一个详细的理解,当然这篇文章也是承接上篇文章,所以强烈建议先阅读上篇文章: Android开发之Tween(补间动画)完全解析(上) ,这篇文章将从代码的角度实现上篇文章的效果。 如有疑问请留言,如有谬误欢迎批评指正。 Tw