java注解(Annotation)
java注解的知识可以分成两部分:生成注解和使用注解。
1、生成注解
1.1、注解的保持范围,用Retention注解实现
也就是说在源代码中产生的注解在哪里可以得到,通过一个枚举类型,将
此范围分成3种:
RetentionPolicy.CLASS:编译器将把注解记录在类文件中,
但在运行时 VM 不需要保留注解。也就是说,通过反射拿不到这种类型的
注解。
RetentionPolicy.RUNTIME:编译器将把注解记录在类文件中,在运行时
VM 将保留注解,因此可以反射性地读取。这种注解应该是我们开发人员
常用的类型。
RetentionPolicy.SOURCE:编译器要丢弃的注解。
1.2、注解的使用范围,用Target注解实现
也就是说编写的注解可以应用在哪里。同样是通过一个枚举类型,将此
范围分成8种:
ElementType.ANNOTATION_TYPE:注释类型
ElementType.CONSTRUCTOR:构造方法
ElementType.FIELD:字段声明(包括枚举常量)
ElementType.LOCAL_VARIABLE:局部变量声明
ElementType.METHOD:方法声明
ElementType.PACKAGE:包声明
ElementType.PARAMETER:参数声明
ElementType.TYPE:类、接口(包括注释类型)或枚举声明
1.3、注解的继承性,用Inherited注解实现
也就是说如果一个注解被此注解所修饰,则该注解是可以被继承的。
1.4、注解的类型:
根据我现在的理解,我把注解分成两类,第一类是标记性的,本身不
包含值,只起到标记的作用,定义时通过如下方式:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Zero {},方法体中没有值,
使用时通过isAnnotationPresent(Class<? extends Annotation> annotationClass)
来判断目标对象是否被注解;
第二类,注解中包含值,定义时通过如下方式:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldNm {
String value();
},
其中value是注解的默认值名,当然也可以使用自己定义的其他名字,
关于在注解中可以使用的值类型,java也是有规定的:
only primitive type, String, Class,annotation, enumeration
are permitted or 1-dimensional arrays thereof
2、注解的使用:
在使用注解时,如果定义时注解有值,并且是用value()来定义的,
则可以直接使用,如下:
@FieldNm("address");
而如果不是用value()来定义的,则需要加上定义时的变量名,如下:
@FieldNm(name="address");
如果该注解仅是一个标记性注解或该注解有默认的值,则直接使用即可,
如下:
@FieldNm
一般情况应该是注解的使用有两类程序员,一类程序员(生产者),定义
注解,并且在程序中解析使用了注解的代码;另一类程序员(消费者),
则在程序的源代码中使用生产者事先定义好的注解。
注解的解析必须依赖反射,为此,几个反射类(AccessibleObject,
Class, Constructor, Field, Method, Package)都实现了
java.lang.reflect.AnnotatedElement接口,以方便注解的获取,可以
通过<T extends Annotation> T getAnnotation(Class<T> annotationClass)
方法获取指定的注解,接着就可以获取该注解的value值了。
附录:我的注解使用心得:
注解应该是属于非常规的一种编程方式,我们一般编写的程序都是让业务用户
使用,而注解的使用对象却是我们的程序源代码,可以说,注解是操作程序
的程序,属于一种元编程。
前几天开发6个查询页面,在写了3个查询页面后,发现这种类型的查询是
有规律的,都是根据页面上传过来的值,拼成一个查询条件,交给数据库
进行处理。在拼查询条件时,基本上都是对查询条件类中的属性进行检测,
如果满足条件,则为合法的条件,并赋予相应的查询比较符,拼到查询字符
串后。由此想到了使用反射加注解的方式,在此,根据实际应用设计了3个
注解,Compare(比较符,默认都为=,可以通过设置注解来改变,比如可以
为">","like"等数据库中使用的比较符);Zero(0是否有效注解,这是一个
标记类型的注解,表示如果字段为0,这个0是否需要作为查询条件,默认
0不是合法的查询条件);FieldNm(字段名映射注解,有时页面上传过来的
参数可能和数据库中的字段名不一样,用这个注解来标示数据库中实际的字
段名),最后,通过反射去分析查询类,根据注解的规则生成相应的查询
条件。
使用了注解的解决方案后,感觉豁然开朗了些,平淡的开发中也可以有
不平淡的方法。