Java 注解Annotation使用解析

原址:点击打开链接

Java 注解Annotation使用解析

注解简介

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

注解Annotation是Java5引入的新特性。它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。更通俗的意思是为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且是供指定的工具或框架使用的。

Annontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中,它被置于注解项之前,中间没有分号(修饰符就是诸如public或者static之类的关键字)。每一个注解前面都会加上一个@符号。

注解原理

Annotation其实是一种接口。通过Java的反射机制相关的API来访问Annotation信息。相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。

Annotation是不会影响程序代码的执行,无论Annotation怎么变化,代码都始终如一地执行。

Java编译器在工作时会忽略这些Annotation,因此在JVM 中这些Annotation是“不起作用”的,Java编译器对于包含注解和不包含注解的代码会生成相同的虚拟器指令。因此如果想在实际开发中使用注解,必须得有对Annotation进行访问和处理的工具才行,这也是使用注解的核心所在。

注解语法

注解由注解接口定义的:

每个元素elementDeclaration的声明都具有下面这种形式:

举个示例说明一下注解:

元素的顺序无关紧要,下面两个注解是一样效果的

@Model(name=”admin”,age=20)或
@Model(age=20,name=”admin”)

如果某个元素的值未指定,那么就使用声明的默认值。

@Model(age=20)

元素name的默认值就是”_name”。

如果没有指定元素,要么注解中没有任何元素,要么所有元素都使用默认值,这时候可以不用指定括号了。

@Model与@Model(name=”_name”,age=0)是一样的。

如果一个注解只有一个元素,并且元素的名称为value,这时候可以忽略这个元素及等号,该种方式的注解一般称为单值注解

示例如下:

@OnClick(value=R.id.btn)与@OnClick(R.id.btn)一样。

所有的注解都隐式地扩展自java.lang.annotation.Annotation接口,该接口是一个常规接口,并不是一个注解接口,开发者不可以扩展注解接口。

注解接口中的元素声明实际上是方法声明。一个注解接口的方法不能有任何的参数和任何throws语句,并且也不能是泛型。

一个注解元素永远不能为null,默认值也不允许为null。可以使用其它默认值,如””或者Void.class。

如果元素值是一个数组,它的值需要用括号括起来,如果具有单值则可以忽略大括号,如下:

@Model(…,hobby={“reading”,”writting”})

数组单值如下:

@Model(…,hobby=”reading”)

一个注解可以引用另一个注解,例如:

@Model(ref=@Bean(name=”admin”),…)

一个项可以有多个注解,但是这些注解必须是属于不同类型

注解可以声明的类型如下:

  • 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
  • String类型
  • Class类型
  • enum类型
  • Annotation类型
  • 以上所有类型的数组(有数组组成的数组除外)

下面是一个合法声明的示例:

可以向注解中添加如下的项:

  • 类(包括enum)
  • 接口(包括注解接口)
  • 方法
  • 构造器
  • 实力域
  • 局部变量
  • 参数变量

注解类型

JavaSE在java.lang、java.lang.annotation和javax.annotation包中定义了大量注解接口。其中四个是元注解,用于描述注解接口的行为属性。

注解接口 应用场合 目的
Deprecated 全部 将项标记为过时的
SuppressWarnings 除了包和注解之外的所有情况 组织某个给定类型的警告信息
Override 方法 检测该方法是否覆盖了某一个超类的方法
PostConstruct
PreDestroy
被标记的方法应该在构造之后或者移除之前立即被调用 XXXXX
Resource 类、接口、方法、域 在类或接口上:标记为在其他地方要用到的资源。在方法或域上:为“注入”而标记
Resources 类、接口 一个资源数组
Generated 全部 提供代码生成工具使用
Target 注解 指明可以应用这个注解的哪些项
Retention 注解 指明这个注解可以保留多久
Documented 注解 指明这个注解应该包含在注解项的文档中
Inherited 注解 指明当这个注解应用于一个类的时候,能够自动被它的子类继承

@Deprecated注解表示该项是不被建议使用的。所以当我们使用一个已过时的项时,编译器将会发出警告。

@SuppressWarnings注解会告知编译器阻止特殊类型的警告信息。

@SuppressWarnings(“unchecked”)

@Override注解只能用在方法上。编译器会检查一个方法是否正在覆盖了父类的方法。

其它的几个注解项这里就不做解释了。

元注解

@Target元注解可以应用于一个注解,以限制该注解可以应用到哪些项上面。例如:

@Target注解类型如下表:

元素类型注解使用场合
ANNOTATION_TYPE注解类型声明
PACKAGE
TYPE类(包括enum)及接口(包括注解类型)
METHOD方法
CONSTRUCTOR构造器
FIELD成员域(包括enum常量)
PARAMETER方法或构造器参数
LOCAL_VARIABLE局部变量

一条没有@Target限制的注解可以应用于任何项上面。编译器会检查是否将一个注解只应用到了某个允许的项上面。

@Retention用于指定一个注解可以停留多长时间。其的默认值是RetentionPolicy.CLASS。

保留规则描述
SOURCE注解会被编译器忽略,并只会保留在源代码中
CLASS注解会通过编译驻留在CLASS文件,但会被JVM在运行时忽略,正因为如此,其在运行时不可见
RUNTIME注解会被JVM获取,并在运行时通过反射获取

@Inherited元注解只能应用于对类的注解,它所有的子类都会自动具有同样的注解。这并不代表接口就不可以使用,在接口上使用该注解,只是说该注解不会起任何作用,其实现类不会继承接口中的任何注解。

@Documented 将此注解包含在 javadoc 中。

自定义注解

很多第三方框架都是支持注解操作的,如Android xUtils以及Retrofit、Hibernate等。在Android开发中有许多针对数据库操作的ORM框架,如xUtils和GreenDAO。下面通过一个非常简单的示例查看一下如何通过注解来实现ORM机制。

先自定义一个注解@Table,通过注解解析器我们可以构建一个数据库表格。

下面是表格列的注解@Column,通过该注解我们可以解析出属性通表格列的对应关系。

两个自定义注解已经定义好了,通过文章开始部分分析我们知道,如果没有注解解析器,注解也就没有任何实际意义了。

Java反射API包含了许多方法来在运行时从类,方法或者其它元素获取注解。接口AnnotatedElement包含了大部分重要的方法,如下:

  • boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)如果该项具有给定类型的注解,则返回true。
  • <T extends Annotation> T getAnnotation(Class<T> annotationClass)获得给定类型的注解,如果该项不具有该类型的注解,则返回null。
  • Annotation[] getAnnotations()获得作用于该项的所有注解,包括继承而来的注解。如果没有任何注解,将返回一个长度为0的数组。
  • Annotation[] getDeclaredAnnotations()获得为该项声明的所有注解,不包括继承而来的注解。

通过上面介绍给的几个获取注解的方法,通过反射我们就很容易实现一个注解解析器。

注解导图

图片来自网络

annotation

小结

在学习Android的过程中发现很多第三方或者官方的库都在使用注解,这次抽些时间系统的整理了一下相关知识,还算比较全面。在示例源代码中简单自定义了一个按钮事件的注解,可以直接在处理函数上面注解上相应的按钮即可。

示例源代码下载

本文地址:www.sunnyang.com/413.html

参考资料

深入理解Java:注解(Annotation)自定义注解入门

Java 注解指导手册 – 终极向导

Java注解教程及自定义注解

Java注解(一)

理解Java基础之注解Annotation

********************************************************************

其他文章:

怎样优雅地使用java注解?



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值