原址:点击打开链接
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()获得为该项声明的所有注解,不包括继承而来的注解。
通过上面介绍给的几个获取注解的方法,通过反射我们就很容易实现一个注解解析器。
注解导图
图片来自网络
小结
在学习Android的过程中发现很多第三方或者官方的库都在使用注解,这次抽些时间系统的整理了一下相关知识,还算比较全面。在示例源代码中简单自定义了一个按钮事件的注解,可以直接在处理函数上面注解上相应的按钮即可。
本文地址:www.sunnyang.com/413.html
参考资料
深入理解Java:注解(Annotation)自定义注解入门
********************************************************************
其他文章: