Java学习:Annotation注解

简介: Annotation不算常用的技术,早前用它写了一些玩意儿,过了一年又忘干净了,今天写点东西记下来,以备再忘之需。   java.lang.annotation,接口 Annotation。对于Annotation,是Java5的新特性,JDK5引入了Metedata(元数据)很容易的就能够调用Annotations。

Annotation不算常用的技术,早前用它写了一些玩意儿,过了一年又忘干净了,今天写点东西记下来,以备再忘之需。

 

java.lang.annotation,接口 Annotation。对于Annotation,是Java5的新特性,JDK5引入了Metedata(元数据)很容易的就能够调用Annotations。Annotations提供一些本来不属于程序的数据,比如:一段代码的作者或者告诉编译器禁止一些特殊的错误。An annotation 对代码的执行没有什么影响。Annotations使用@annotation的形式应用于代码:类(class),属性(attribute),方法(method)等等。一个Annotation出现在上面提到的开始位置,而且一般只有一行,也可以包含有任意的参数。

 

——————百度百科

 

Annotation是什么,上面说得很清楚了,下面重点说,它怎么写,和有什么用。

 一、Annotation的基本写法

/**
 * @author caiyu
 * @date 2014-1-21
 */

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSchemaConfig {
    String type() default "get";
    String value();
}

 

1、DataSchemaConfig为Annotation的名称

2、 @Retention 表示该Annotation的保留级别

分别以下三种:

RetentionPolicy.RUNTIME

会记录在CLASS里,同时会在运行时保留该注解,以使其可以被反射读取。

RetentionPolicy.SOURCE

只存在于源码里,会被编译器抛弃

RetentionPolicy.CLASS

会被编译器记录在CLASS文件中,但虚拟机不会在运行时保留它。该选项是默认选项

3、@Target表示该Annotation的影响范围,如下所示:

package java.lang.annotation;

/**
 * A program element type.  The constants of this enumerated type
 * provide a simple classification of the declared elements in a
 * Java program.
 *
 * <p>These constants are used with the {@link Target} meta-annotation type
 * to specify where it is legal to use an annotation type.
 *
 * @author  Joshua Bloch
 * @since 1.5
 */
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE
}

 

4、内容组织形式

String type() default "get";

 这段声明里,String为成员类型,type为成员名称(必须写上括号),default "get"表示缺省指为"get"

 

5、使用见如下示例代码

  

/**
 * @author caiyu
 * @date 2014-1-22
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DataType {
    public String value() default "map";
}



@DataType(value = "bean")
public class MapModel {
    private Map<String, Object> o = new HashMap<String, Object>();

    @GET
    public Object get(String key) {
        return o.get(key);
    }

    @PUT
    public void put(String key, Object value) {
        o.put(key, value);
    }
}

 

DataType 这个Annotation被声明为Runtime以及TYPE,所以它可以被用于注解MapModel这个类。
括号里的value="bean",则是为其value赋值1,同时由于value是个特殊成员,可以写作
@DataType("bean")

  如果写作

@DataType

  则value会使用默认值"map"

 

6、数组形式的成员类型的使用

 把上面的内容改成下面的格式:

String[] value() default "map";

之前的这种写法@DataType("bean")仍然是合法的

  同时可以写作@DataType({"map","bean"})

 

 

 二、Annotaion的用途

在介绍@Retention的时候,其实已经说明了Annotation的三种类型了,SOURCE和CLASS类型使用很少,如果你不是需要自己写一个Java Compiler或者Editor,基本用不上。

这里重点说说RUNTIME类型。

我们知道,RUNTIME会被保存在CLASS文件中,而且其中记录的信息可以通过反射来获取到,于是可以利用这点实现一些方便的配置(比如Spring和Hibernate就是利用这点)。

 来看看一个MapModel类:

@DataType
public class MapModel {
    private Map<String, Object> o = new HashMap<String, Object>();

    @get
    public Object getProperty(String key) {
        return o.get(key);
    }

    @put
    public void putProperty(String key, Object value) {
        o.put(key, value);
    }

    public String toString() {
        return o.toString();
    }
}

 

可以看到,MapModel标记了三个注解,分别是DataType和get、put

下面的代码,是用来把该Model和org.dom4j.Element相互转换的,注意只能参考,并不完整:

/**
     * 序列化注解类型
     * 
     * @param content
     * @param schema
     * @return
     */
    private Element serialMapType(Object content, IDataSchema<?> schema) {
        DataType type = schema.getType().getAnnotation(DataType.class);
        if (type != null && type.value() == DataTypeValue.MAP) {
            Element root = DocumentFactory.getInstance().createElement(
                    schema.getName());

            Method getMethod = extraMethodByAnnotation(schema.getType(),
                    get.class);
            if (getMethod == null)
                throw new InvalidAnnotationConfigException(
                        "Invalid annotation class: "
                                + schema.getType().getName());
            try {
                for (Entry<String, IDataSchema<?>> field : schema
                        .getFieldEntrySet()) {
                    Object o = getMethod.invoke(content, field.getValue()
                            .getId());
                    Element e = save(o, field.getValue());
                    root.add(e);
                }
                return root;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                throw new InvalidAnnotationConfigException(
                        "Invalid put method : " + getMethod.getName());
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

        }

        return null;
    }



    /**
     * 反序列化注解类型数据
     * 
     * @param persistentTarget
     * @param schema
     * @return
     */
    private Object deserialMapType(Element persistentTarget,
            IDataSchema<?> schema) {
        Object instance = null;
        DataType type = schema.getType().getAnnotation(DataType.class);
        if (type != null && type.value() == DataTypeValue.MAP) {
            Method putMethod = extraMethodByAnnotation(schema.getType(),
                    put.class);
            if (putMethod == null)
                throw new InvalidAnnotationConfigException(
                        "Invalid annotation class: "
                                + schema.getType().getName());
            try {
                instance = schema.getType().newInstance();
                for (Entry<String, IDataSchema<?>> field : schema
                        .getFieldEntrySet()) {
                    Element e = persistentTarget.element(field.getValue()
                            .getName());
                    Object v = load(e, field.getValue());
                    putMethod.invoke(instance, new Object[] {
                            field.getValue().getId(), v });
                }
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                throw new InvalidAnnotationConfigException(
                        "Invalid put method : " + putMethod.getName());
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return instance;
    }

 

 

    /**
     * 抽取含有指定注解的方法
     * 
     * @param type
     * @param annotationClass
     * @return
     */
    private Method extraMethodByAnnotation(Class<?> type,
            Class<? extends Annotation> annotationClass) {
        for (Method method : type.getDeclaredMethods()) {
            Annotation t = method.getAnnotation(annotationClass);
            if (t != null) {
                return method;
            }

        }
        return null;
    }

 

 

 

目录
相关文章
|
12月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
525 1
|
Java API 容器
Java基础学习day08-2
本节讲解Java方法引用与常用API,包括静态、实例、特定类型方法及构造器引用的格式与使用场景,并结合代码示例深入解析。同时介绍String和ArrayList的核心方法及其实际应用。
292 1
|
12月前
|
存储 Oracle Java
java零基础学习者入门课程
本课程为Java零基础入门教程,涵盖环境搭建、变量、运算符、条件循环、数组及面向对象基础,每讲配示例代码与实践建议,助你循序渐进掌握核心知识,轻松迈入Java编程世界。
878 0
|
12月前
|
负载均衡 Java API
grpc-java 架构学习指南
本指南系统解析 grpc-java 架构,涵盖分层设计、核心流程与源码结构,结合实战路径与调试技巧,助你从入门到精通,掌握高性能 RPC 开发精髓。
1043 8
|
Java
Java基础学习day08-作业
本作业涵盖Java中Lambda表达式的应用,包括Runnable与Comparator接口的简化实现、自定义函数式接口NumberProcessor进行加减乘及最大值操作,以及通过IntProcessor处理整数数组,实现遍历、平方和奇偶判断等功能,强化函数式编程实践。
207 5
|
Java 程序员
Java基础学习day08
本节讲解Java中的代码块(静态与实例)及其作用,深入介绍内部类(成员、静态、局部及匿名)的定义与使用,并引入函数式编程思想,重点阐述Lambda表达式及其在简化匿名内部类中的应用。
300 5
|
Java
Java基础学习day07-作业
本作业包含六个Java编程案例:1)动物类继承与多态;2)加油卡支付系统;3)员工管理类设计;4)学生信息统计接口;5)USB设备控制;6)家电智能控制。综合运用抽象类、接口、继承、多态等面向对象技术,强化Java基础编程能力。
364 3
|
设计模式 XML Java
让别人和自己看懂自己的程序代码?一文掌握Java单行多行、文档注释以及注解(Annotation)超详细的理解使用,IDEA注释注解快捷键和模板,提高程序代码更有可读性
让别人和自己看懂自己的程序代码?一文掌握Java单行多行、文档注释以及注解(Annotation)超详细的理解使用,IDEA注释注解快捷键和模板,提高程序代码更有可读性
让别人和自己看懂自己的程序代码?一文掌握Java单行多行、文档注释以及注解(Annotation)超详细的理解使用,IDEA注释注解快捷键和模板,提高程序代码更有可读性
|
设计模式 Java
Java学习路线-6:Annotation注解、多态和抽象类(3)
Java学习路线-6:Annotation注解、多态和抽象类
303 0
Java学习路线-6:Annotation注解、多态和抽象类(2)
Java学习路线-6:Annotation注解、多态和抽象类
268 0