Java注解总结

来源:互联网 发布:php网店 编辑:程序博客网 时间:2024/05/18 17:59

Java注解,从字面上看是注释、解释,但功能远不只这么简单。注解(Annotation)为我们在代码中添加信息提供一种形式化的方法,使我们可以在稍后某个时刻方便使用这些数据(通过解析注解来使用这些数据),常见作用有:

1.生成文档。这是最常见的,也是java 最早提供的注解。常用的有@see @param @return 等

2.跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量。

3.在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。


包 java.lang.annotation 中包含所有定义自定义注解所需用到的原注解和接口。

如接口 java.lang.annotation.Annotation 是所有注解继承的接口,并且是自动继承,不需要定义时指定,类似于所有类都自动继承Object。

该包同时定义了四个元注解,@Target@Retention@Inherited@Documented。下面将在实例中逐个讲解他们的作用及使用方法。

@Target : 表示该注解用于什么地方,可能的值在枚举类型 ElemenetType中,包括: 

 ElemenetType.CONSTRUCTOR       构造器声明 
 ElemenetType.FIELD              域声明(包括 enum 实例) 
 ElemenetType.LOCAL_VARIABLE     局部变量声明 
 ElemenetType.METHOD              方法声明 
 ElemenetType.PACKAGE            包声明 
 ElemenetType.PARAMETER            参数声明 
 ElemenetType.TYPE               类,接口(包括注解类型)或enum声明

@Retention:表示在什么级别保存该注解信息,可选的参数值在枚举类型 RetentionPolicy 中,包括:

RetentionPolicy.SOURCE 作用是不将注解保存在class文件中,也就是说象“//”一样在编译时被过滤掉了。

RetentionPolicy.CLASS 作用是只将注解保存在class文件中,而使用反射读取注解时忽略这些注解。

RetentionPolicy.RUNTIME 作用是既将注解保存在class文件中,也可以通过反射读取注解,这也是最常用的值。

@Inherited:继承是java主要的特性之一。在类中的protected和public成员都将会被子类继承,但是父类的注解会不会被子类继承呢?很遗憾的告诉大家,在默认的情况下,父类的注解并不会被子类继承。如果要让这个注解可以被继承,就必须在定义注解时在源码上加上@Inherited注解。 

@Documented:在默认的情况下在使用javadoc自动生成文档时,注解将被忽略掉。如果想在文档中也包含注解,必须使用Documented为文档注解。


如何读取注解--类上的注解

// 取得类上的指定的注解Annotation annotation = 类.class.getAnnotation(MyAnnotation.class);  // 取得类上的所有注解,包括继承的注解Annotation[] annotations = 类.class.getAnnotations();  // 取当前类上的所有的注解,不包括继承的Annotation[] annotations = 类.class.getDeclaredAnnotations();  


如何读取注解--方法上的注解

// 取得方法上的指定的注解Method m = ...Annotation annotation = m.getAnnotation(MyAnnotation.class);// 取得方法上的所有注解,包括继承的注解Annotation[] annotations = m.getAnnotations();  // 取得方法上的所有注解,不包括继承的注解Annotation[] annotations = m.getDeclaredAnnotations();


如何读取注解--构造方法上的注解

// 取得构造方法上的指定的注解Constructor c =...Annotation annotation = c.getAnnotation(MyAnnotation.class);// 取得构造方法上的所有注解,包括继承的注解Annotation[] annotations = c.getAnnotations();// 取得构造方法上的所有注解,不包括继承的注解Annotation[] annotations = c.getDeclaredAnnotations();

如何读取注解--字段上的注解

// 取得属性字段上的指定的注解Field f =...Annotation annotation = f.getAnnotation(MyAnnotation.class);// 取得属性字段上的所有注解,包括继承的注解Annotation[] annotations = f.getAnnotations();// 取得属性字段上的所有注解,不包括继承的注解Annotation[] annotations = f.getDeclaredAnnotations();


我们先建立第一个注解,TestA.java

备注:@interface用来声明一个注解,其中的每一个方法实际上是声明了注解的一个配置参数,方法的名称就是参数的名称,返回值类型就是参数的类型,可以通过default来声明参数的默认。至于注解用在什么地方、在什么级别保存该注解信息是由元注解来控制。

package testannotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * @author quyang.ybb * */@Target({ ElementType.PACKAGE, ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD })@Retention(RetentionPolicy.RUNTIME)public @interface TestA {    String name();    int id() default 0;    Class<Long> func();}

package testannotation;import java.util.HashMap;import java.util.Map;/** * @author quyang.ybb * */@TestA(name = "type", func = Long.class)public class UserAnnotation {    @TestA(name = "param", id = 1, func = Long.class)    private Integer age;    @TestA(name = "constructor", id = 2, func = Long.class)    public UserAnnotation() {this.age = 22;    }    @TestA(name = "public method", id = 3, func = Long.class)    public void a() {Map<String, String> m = new HashMap<String, String>(0);    }    @TestA(name = "protected method", id = 4, func = Long.class)    protected void b() {Map<String, String> m = new HashMap<String, String>(0);    }    @TestA(name = "private method", id = 5, func = Long.class)    private void c() {Map<String, String> m = new HashMap<String, String>(0);    }}


package testannotation;import java.lang.annotation.Annotation;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * @author quyang.ybb * */public class ParseAnnotation {    public static void parseTypeAnnotation() throws ClassNotFoundException {Class clazz = Class.forName("testannotation.UserAnnotation");Annotation[] annotations = clazz.getAnnotations();for (Annotation annotation : annotations) {    TestA testA = (TestA) annotation;    System.out.println("type name = " + clazz.getName() + " | id = " + testA.id() + " | name = " + testA.name()    + " | func = " + testA.func());}    }    public static void parseMethodAnnotation() throws Exception {// getMethods()与getDeclaredMethods()try {    // just try to validate getMethod(), because a() has not parameters    Method mt = UserAnnotation.class.getMethod("a");    System.out.println(mt.getName());} catch (Exception e) {    e.printStackTrace();}Method[] methods = UserAnnotation.class.getDeclaredMethods();for (Method method : methods) {    boolean hasAnnotation = method.isAnnotationPresent(TestA.class);    if (hasAnnotation) {TestA testA = method.getAnnotation(TestA.class);System.out.println("method name = " + method.getName() + " | id = " + testA.id() + " | name = "+ testA.name() + " | func = " + testA.func());    }}    }    @SuppressWarnings({ "rawtypes", "unchecked" })    public static void parseConstructorAnnotation() throws ClassNotFoundException {Constructor[] construtors = UserAnnotation.class.getConstructors();for (Constructor constructor : construtors) {    boolean hasAnnotation = constructor.isAnnotationPresent(TestA.class);    if (hasAnnotation) {TestA testA = (TestA) constructor.getAnnotation(TestA.class);System.out.println("constructor name = " + constructor.getName() + " | id = " + testA.id()+ " | name = " + testA.name() + " | func = " + testA.func());    }}    }    public static void parseFieldAnnotation() throws ClassNotFoundException {// getFields()与getDeclaredFields()Field[] fields = UserAnnotation.class.getDeclaredFields();for (Field field : fields) {    boolean hasAnnotation = field.isAnnotationPresent(TestA.class);    if (hasAnnotation) {TestA testA = field.getAnnotation(TestA.class);System.out.println("Field name = " + field.getName() + " | id = " + testA.id() + " | name = "+ testA.name() + " | func = " + testA.func());    }}    }    public static void main(String[] args) throws Exception {parseTypeAnnotation();parseMethodAnnotation();parseConstructorAnnotation();parseFieldAnnotation();    }}

打印结果:

type name = testannotation.UserAnnotation | id = 0 | name = type | func = class java.lang.Long

a

method name = c | id = 5 | name = private method | func = class java.lang.Long

method name = a | id = 3 | name = public method | func = class java.lang.Long

method name = b | id = 4 | name = protected method | func = class java.lang.Long

constructor name = testannotation.UserAnnotation | id = 2 | name = constructor | func = class java.lang.Long

Field name = age | id = 1 | name = param | func = class java.lang.Long

备注:  

1. 要用好注解,必须熟悉java 的反射机制,从上面的例子可以看出,注解的解析完全依赖于反射。

2. 不要滥用注解,平常我们编程过程很少接触和使用注解,只有做设计,且不想让设计有过多的配置时。

0 0
原创粉丝点击