Sample:
Android下的RemoteViews, RemoteViews.RemoteView, TextView
#############################################################################################
Annotation 入门实例:一分钟了解Annotation
(http://01404421.iteye.com/blog/568720)
Annotation对很多Javaer来说是一个熟悉的名词,我也是,但是今天涉及到此方面的东西,才发现自己对这个新特性知之甚少,从网上看了下资
料,自己做了个例子,才逐渐明白,例子贴出来方便其他入门者参考。高手就不用看了,只适用于刚接触Annotation者,呵呵,因为我也刚接触。
测试一
1.自定义一个Annotation
-
@Retention(RetentionPolicy.RUNTIME)
-
@Target(ElementType.FIELD)
-
public @interface IdAnnation {
-
}
@Retention(RetentionPolicy.RUNTIME)这个meta-annotation表示了此类型的
annotation将被虚拟机保留使其能够在运行时通过反射被读取。而@Target(ElementType. FIELD)表示此类型的
annotation只能用于修饰属性。
2.使用Annotation
-
public class UserPojo {
-
@IdAnnation
-
String id;
-
String name;
-
}
3.测试
-
import java.lang.reflect.Field;
-
public class Test {
-
public static void main(String[] args) throws Exception{
-
for(Field f:UserPojo.class.getDeclaredFields()){
-
System.out.println(f.getName()+" "+f.isAnnotationPresent(IdAnnation.class) );
-
}
-
}
-
}
输出:
注意:如果在定义Annotation时没有加@Retention(RetentionPolicy.RUNTIME),则程序结果为:
测试二:
1.定义Annotation
-
@Retention(RetentionPolicy.RUNTIME)
-
@Target(ElementType.FIELD)
-
public @interface IdAnnation {
-
String type();
-
}
可以看到,我加入了一个方法。注意Annotation中的方法:
Annotation类型的方法定义是独特的、受限制的,方法必须声明为无参数、无异常抛出的。这些方法定义了annotation的成员:方法名成为了
成员名,而方法返回值成为了成员的类型。而方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面
类型之一作为元素的一维数组。方法的后面可以使用default和一个默认数值来声明成员的默认值,null不能作为成员默认值,这与我们在非
annotation类型中定义方法有很大不同。
2.使用
-
public class UserPojo {
-
@IdAnnation(type="ttttt")
-
String id;
-
String name;
-
}
3.测试
-
import java.lang.reflect.Field;
-
-
public class Test {
-
public static void main(String[] args) throws Exception{
-
for(Field f:UserPojo.class.getDeclaredFields()){
-
System.out.println(f.getName()+" "+f.isAnnotationPresent(IdAnnation.class) );
-
if(f.isAnnotationPresent(IdAnnation.class)){
-
System.out.println(((IdAnnation)f.getAnnotation(IdAnnation.class)).type());
-
}
-
}
-
}
-
}
运行输出:
也不多说了,大家自己多练练,还有方法声明上的Annotion,特别注意class、Filed、Method的所有方法,这是最java基础和核心的东西,应该熟练掌握。
====================================================
一下是Meta-Annotation类型说明:
Annotation
类型可以被它们自己所标注。Java5.0定义了4个标准的meta-annotation类型,分别是:Target、Retention、
Documented、Inherited,它们被用来提供对其它annotation类型作说明。
这些类型和它们所支持的类在java.lang.annotation包中可以找到。
@Target的用法:指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。
ElementType.ANNOTATION_TYPE 应用于注释类型声明
ElementType.CONSTRUCTOR 构造方法声明
ElementType.FIELD 应用于字段声明(包括枚举常量)
ElementType.LOCAL_VARIABLE 应用于局部变量声明
ElementType.METHOD 应用于方法声明
ElementType.PACKAGE 应用于包声明
ElementType.PARAMETER 应用于参数声明
ElementType.TYPE 应用于类、接口(包括注释类型)或枚举声明
----------------------------------------------
@Retention的用法:指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。
RetentionPolicy.CLASS 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释
RetentionPolicy.RUNTIME 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取
RetentionPolicy.SOURCE 编译器要丢弃的注释
-----------------------------------------------
@Documented的用法:指示某一类型的注释将通过 javadoc
和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用 Documented
来注释的,则其注释将成为注释元素的公共 API 的一部分。Documented是一个没有成员的注释。
------------------------------------------------
@Inherited的用法:指示注释类型自动被子类继承。 Inherited也是一个没有成员的注释。
注意,如果使用@Inherited注释类以外的任何事物都是无效的。还要注意,此元注释仅对从超类继承注释有效;对已实现接口的注释无效。
#############################################################################################
实战篇:设计自己的Annotation
(/blog/36659)
Annotation在java的世界正铺天盖地展开,有空写这一篇简单的annotations的文章,算是关于Annotation入门的文章吧,希望能各位们能抛砖,共同学习......
不讲废话了,实践才是硬道理.
第一部分:了解一下java1.5起默认的三个annotation类型:
一个是@Override:只能用在方法之上的,用来告诉别人这一个方法是改写父类的。
一个是@Deprecated:建议别人不要使用旧的API的时候用的,编译的时候会用产生警告信息,可以设定在程序里的所有的元素上.
一个是@SuppressWarnings:这一个类型可以来暂时把一些警告信息消息关闭.
如果不清楚上面三个类型的具体用法,各位可以baidu或google一下的,很简单的。
第二部分:讲一下annotation的概念先,再来讲一下怎样设计自己的annotation.
首先在jdk自带的java.lang.annotation包里,打开如下几个源文件:
1、源文件Target.java
-
@Documented
-
@Retention(RetentionPolicy.RUNTIME)
-
@Target(ElementType.ANNOTATION_TYPE)
-
public @interface Target {
-
ElementType[] value();
-
}
其中的@interface是一个关键字,在设计annotations的时候必须把一个类型定义为@interface,而不能用class或interface关键字(会不会觉得sun有点吝啬,偏偏搞得与interface这么像).
2、源文件Retention.java
-
@Documented
-
@Retention(RetentionPolicy.RUNTIME)
-
@Target(ElementType.ANNOTATION_TYPE)
-
public @interface Retention {
-
RetentionPolicy value();
-
}
看到这里,大家可能都模糊了,都不知道在说什么,别急,往下看一下.
在上面的文件都用到了RetentionPolicy,ElementType这两个字段,你可能就会猜到这是两个java文件.的确,这两个文件的源代码如下:
3、源文件RetentionPolicy.java
-
public enum RetentionPolicy {
-
SOURCE,
-
CLASS,
-
RUNTIME
-
}
这是一个enum类型,共有三个值,分别是SOURCE,CLASS 和 RUNTIME.
SOURCE代表的是这个Annotation类型的信息只会保留在程序源码里,源码如果经过了编译之后,Annotation的数据就会消失,并不会保留在编译好的.class文件里面。
ClASS的意思是这个Annotation类型的信息保留在程序源码里,同时也会保留在编译好的.class文件里面,在执行的时候,并不会把这一些信
息加载到虚拟机(JVM)中去.注意一下,当你没有设定一个Annotation类型的Retention值时,系统默认值是CLASS.
第三个,是RUNTIME,表示在源码、编译好的.class文件中保留信息,在执行的时候会把这一些信息加载到JVM中去的.
举一个例子,如@Override里面的Retention设为SOURCE,编译成功了就不要这一些检查的信息;相反,@Deprecated里面的
Retention设为RUNTIME,表示除了在编译时会警告我们使用了哪个被Deprecated的方法,在执行的时候也可以查出该方法是否被
Deprecated.
4、源文件ElementType.java
-
public enum ElementType {
-
TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR,
-
LOCAL_VARIABLE, ANNOTATION_TYPE,PACKAGE
-
}
@Target里面的ElementType是用来指定Annotation类型可以用在哪一些元素上的.说明一下:TYPE(类型),
FIELD(属性), METHOD(方法), PARAMETER(参数),
CONSTRUCTOR(构造函数),LOCAL_VARIABLE(局部变量),
ANNOTATION_TYPE,PACKAGE(包),其中的TYPE(类型)是指可以用在Class,Interface,Enum和
Annotation类型上.
另外,从1的源代码可以看出,@Target自己也用了自己来声明自己,只能用在ANNOTATION_TYPE之上.
如果一个Annotation类型没有指明@Target使用在哪些元素上,那么它可以使用在任何元素之上,这里的元素指的是上面的八种类型.
举几个正确的例子:
@Target(ElementType.METHOD)
@Target(value=ElementType.METHOD)
@Target(ElementType.METHOD,ElementType.CONSTRUCTOR)
具体参考一下javadoc文档
上面一下1和2的源文件,它们都使用了@Documented,@Documented的目的就是让这一个Annotation类型的信息能够显示在javaAPI说明文档上;没有添加的话,使用javadoc生成API文档的时候就会找不到这一个类型生成的信息.
另外一点,如果需要把Annotation的数据继承给子类,那么就会用到@Inherited这一个Annotation类型.
第三部分:下面讲的设计一个最简单的Annotation例子,这一例子共用四个文件;
1、Description.java
-
package lighter.iteye.com;
-
-
import java.lang.annotation.Documented;
-
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)
-
@Documented
-
public @interface Description {
-
String value();
-
}
说明:所有的Annotation会自动继承java.lang.annotation这一个接口,所以不能再去继承别的类或是接口.
最重要的一点,Annotation类型里面的参数该怎么设定:
第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型.
第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和
String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String
value();这里的参数成员就为String.
第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:上面的例子就只有一个参数成员.
2、Name.java
-
package lighter.iteye.com;
-
-
import java.lang.annotation.Documented;
-
import java.lang.annotation.ElementType;
-
import java.lang.annotation.Retention;
-
import java.lang.annotation.RetentionPolicy;
-
import java.lang.annotation.Target;
-
-
-
@Target(ElementType.METHOD)
-
@Retention(RetentionPolicy.RUNTIME)
-
@Documented
-
public @interface Name {
-
String originate();
-
String community();
-
}
3、JavaEyer.java
-
package lighter.iteye.com;
-
-
@Description("javaeye,做最棒的软件开发交流社区")
-
public class JavaEyer {
-
@Name(originate="创始人:robbin",community="javaEye")
-
public String getName()
-
{
-
return null;
-
}
-
-
@Name(originate="创始人:江南白衣",community="springside")
-
public String getName2()
-
{
-
return "借用两位的id一用,写这一个例子,请见谅!";
-
}
-
}
4、最后,写一个可以运行提取JavaEyer信息的类TestAnnotation
-
package lighter.iteye.com;
-
-
import java.lang.reflect.Method;
-
import java.util.HashSet;
-
import java.util.Set;
-
-
public class TestAnnotation {
-
-
-
-
-
public static void main(String[] args) throws Exception {
-
String CLASS_NAME = "lighter.iteye.com.JavaEyer";
-
Class test = Class.forName(CLASS_NAME);
-
Method[] method = test.getMethods();
-
boolean flag = test.isAnnotationPresent(Description.class);
-
if(flag)
-
{
-
Description des = (Description)test.getAnnotation(Description.class);
-
System.out.println("描述:"+des.value());
-
System.out.println("-----------------");
-
}
-
-
-
Set set = new HashSet();
-
for(int i=0;i
-
{
-
boolean otherFlag = method[i].isAnnotationPresent(Name.class);
-
if(otherFlag) set.add(method[i]);
-
}
-
for(Method m: set)
-
{
-
Name name = m.getAnnotation(Name.class);
-
System.out.println(name.originate());
-
System.out.println("创建的社区:"+name.community());
-
}
-
}
-
}
5、运行结果:
描述:javaeye,做最棒的软件开发交流社区
-----------------
创始人:robbin
创建的社区:javaEye
创始人:江南白衣
创建的社区:springside
这一篇文章写了两个小时有多啦,也算是一篇关于设计自定的Annotation的入门篇啦;另外,特在处声明,如果转载请注明出处:。
参考资料:
1、
2、
3、http://calvin.iteye.com/blog/33210
#############################################################################################
Java Reflection: Annotations
()
Using Java Reflection you can access the annotations attached to Java classes at runtime.
Here is a list of the topics covered in this text:
What are Java Annotations?
Annotations is a new feature from Java 5. Annotations are a kind of comment or meta
data you can insert in your Java code. These annotations can then be processed at
compile time by pre-compiler tools, or at runtime via Java Reflection. Here is
an example of class annotation:
@MyAnnotation(name="someName", value = "Hello World")
public class TheClass {
}
The class TheClass has the annotation @MyAnnotation written ontop.
Annotations are defined like interfaces. Here is the MyAnnotation definition:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
public String name();
public String value();
}
The @ in front of the interface marks it as an annotation. Once
you have defined the annotation you can use it in your code, as shown in the earlier examples.
The two directives in the annotation definition, @Retention(RetentionPolicy.RUNTIME)
and @Target(ElementType.TYPE), specifies how the annotation is to be used.
@Retention(RetentionPolicy.RUNTIME) means that the annotation can be accessed via reflection
at runtime. If you do not set this directive, the annotation will not be preserved at runtime,
and thus not available via reflection.
@Target(ElementType.TYPE) means that the annotation can only be used
ontop of types (classes and interfaces typically). You can also specify METHOD or
FIELD, or you can leave the target out alltogether so the annotation can be used
for both classes, methods and fields.
Class Annotations
You can access the annotations of a class, method or field at runtime. Here is an example that
accesses the class annotations:
Class aClass = TheClass.class;
Annotation[] annotations = aClass.getAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
}
You can also access a specific class annotation like this:
Class aClass = TheClass.class;
Annotation annotation = aClass.getAnnotation(MyAnnotation.class);
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
Method Annotations
Here is an example of a method with annotations:
public class TheClass {
@MyAnnotation(name="someName", value = "Hello World")
public void doSomething(){}
}
You can access method annotations like this:
Method method = ... //obtain method object
Annotation[] annotations = method.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
}
You can also access a specific method annotation like this:
Method method = ... // obtain method object
Annotation annotation = method.getAnnotation(MyAnnotation.class);
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
Parameter Annotations
It is possible to add annotations to method parameter declarations too. Here is how that looks:
public class TheClass {
public static void doSomethingElse(
@MyAnnotation(name="aName", value="aValue") String parameter){
}
}
You can access parameter annotations from the Method object like this:
Method method = ... //obtain method object
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Class[] parameterTypes = method.getParameterTypes();
int i=0;
for(Annotation[] annotations : parameterAnnotations){
Class parameterType = parameterTypes[i++];
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("param: " + parameterType.getName());
System.out.println("name : " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
}
}
Notice how the Method.getParameterAnnotations() method returns a
two-dimensional Annotation array, containing an array of annotations
for each method parameter.
Field Annotations
Here is an example of a field with annotations:
public class TheClass {
@MyAnnotation(name="someName", value = "Hello World")
public String myField = null;
}
You can access field annotations like this:
Field field = ... //obtain field object
Annotation[] annotations = field.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
}
You can also access a specific field annotation like this:
Field field = ... // obtain method object
Annotation annotation = field.getAnnotation(MyAnnotation.class);
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}