一、注解:深入理解JAVA注解

  要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法。

1、元注解(meta-annotation):

  元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
    1.@Target,
    2.@Retention,
    3.@Documented,
    4.@Inherited
  这些类型和它们所支持的类在java.lang.annotation包中可以找到。下面我们看一下每个元注解的作用和相应分参数的使用说明。

@Target:

   @Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。

  作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

  取值(ElementType)有:

    1.CONSTRUCTOR:用于描述构造器
    2.FIELD:用于描述域
    3.LOCAL_VARIABLE:用于描述局部变量
    4.METHOD:用于描述方法
    5.PACKAGE:用于描述包
    6.PARAMETER:用于描述参数
    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

  使用实例:  

  1. @Target(ElementType.TYPE)
  2. public @interface Table {
  3. /**
  4. * 数据表名称注解,默认值为类名称
  5. * @return
  6. */
  7. public String tableName() default "className";
  8. }
  9.  
  10. @Target(ElementType.FIELD)
  11. public @interface NoDBColumn {
  12.  
  13. }

注解Table 可以用于注解类、接口(包括注解类型) 或enum声明,而注解NoDBColumn仅可用于注解类的成员变量。

@Retention:

  @Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。

  作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)

  取值(RetentionPoicy)有:

    1.SOURCE:在源文件中有效(即源文件保留)
    2.CLASS:在class文件中有效(即class保留)
    3.RUNTIME:在运行时有效(即运行时保留)

  Retention meta-annotation类型有唯一的value作为成员,它的取值来自java.lang.annotation.RetentionPolicy的枚举类型值。具体实例如下:

  1. @Target(ElementType.FIELD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface Column {
  4. public String name() default "fieldName";
  5. public String setFuncName() default "setField";
  6. public String getFuncName() default "getField";
  7. public boolean defaultDBValue() default false;
  8. }

 Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理


  @Documented:

  @Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

  1. @Target(ElementType.FIELD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface Column {
  5. public String name() default "fieldName";
  6. public String setFuncName() default "setField";
  7. public String getFuncName() default "getField";
  8. public boolean defaultDBValue() default false;
  9. }

@Inherited:

  @Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

  注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。

  当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。

  实例代码:

  1. /**
  2. *
  3. * @author peida
  4. *
  5. */
  6. @Inherited
  7. public @interface Greeting {
  8. public enum FontColor{ BULE,RED,GREEN};
  9. String name();
  10. FontColor fontColor() default FontColor.GREEN;
  11. }

自定义注解:

  使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

  定义注解格式:
  public @interface 注解名 {定义体}

  注解参数的可支持数据类型:

    1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
    2.String类型
    3.Class类型
    4.enum类型
    5.Annotation类型
    6.以上所有类型的数组

  Annotation类型里面的参数该怎么设定: 
  第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;   
  第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;  
  第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。

  简单的自定义注解和使用注解实例:

  1. package annotation;
  2.  
  3. import java.lang.annotation.Documented;
  4. import java.lang.annotation.ElementType;
  5. import java.lang.annotation.Retention;
  6. import java.lang.annotation.RetentionPolicy;
  7. import java.lang.annotation.Target;
  8.  
  9. /**
  10. * 水果名称注解
  11. * @author peida
  12. *
  13. */
  14. @Target(ElementType.FIELD)
  15. @Retention(RetentionPolicy.RUNTIME)
  16. @Documented
  17. public @interface FruitName {
  18. String value() default "";
  19. }
  1. package annotation;
  2.  
  3. import java.lang.annotation.Documented;
  4. import java.lang.annotation.ElementType;
  5. import java.lang.annotation.Retention;
  6. import java.lang.annotation.RetentionPolicy;
  7. import java.lang.annotation.Target;
  8.  
  9. /**
  10. * 水果颜色注解
  11. * @author peida
  12. *
  13. */
  14. @Target(ElementType.FIELD)
  15. @Retention(RetentionPolicy.RUNTIME)
  16. @Documented
  17. public @interface FruitColor {
  18. /**
  19. * 颜色枚举
  20. * @author peida
  21. *
  22. */
  23. public enum Color{ BULE,RED,GREEN};
  24.  
  25. /**
  26. * 颜色属性
  27. * @return
  28. */
  29. Color fruitColor() default Color.GREEN;
  30.  
  31. }
  1. package annotation;
  2.  
  3. import annotation.FruitColor.Color;
  4.  
  5. public class Apple {
  6.  
  7. @FruitName("Apple")
  8. private String appleName;
  9.  
  10. @FruitColor(fruitColor=Color.RED)
  11. private String appleColor;
  12.  
  13. public void setAppleColor(String appleColor) {
  14. this.appleColor = appleColor;
  15. }
  16. public String getAppleColor() {
  17. return appleColor;
  18. }
  19.  
  20. public void setAppleName(String appleName) {
  21. this.appleName = appleName;
  22. }
  23. public String getAppleName() {
  24. return appleName;
  25. }
  26.  
  27. public void displayName(){
  28. System.out.println("水果的名字是:苹果");
  29. }
  30. }

注解元素的默认值:

  注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为每个注解的声明中,所有元素都存在,并且都具有相应的值,为了绕开这个约束,我们只能定义一些特殊的值,例如空字符串或者负数,一次表示某个元素不存在,在定义注解时,这已经成为一个习惯用法。例如:

  1. package annotation;
  2.  
  3. import java.lang.annotation.Documented;
  4. import java.lang.annotation.ElementType;
  5. import java.lang.annotation.Retention;
  6. import java.lang.annotation.RetentionPolicy;
  7. import java.lang.annotation.Target;
  8.  
  9. /**
  10. * 水果供应者注解
  11. * @author peida
  12. *
  13. */
  14. @Target(ElementType.FIELD)
  15. @Retention(RetentionPolicy.RUNTIME)
  16. @Documented
  17. public @interface FruitProvider {
  18. /**
  19. * 供应商编号
  20. * @return
  21. */
  22. public int id() default -1;
  23.  
  24. /**
  25. * 供应商名称
  26. * @return
  27. */
  28. public String name() default "";
  29.  
  30. /**
  31. * 供应商地址
  32. * @return
  33. */
  34. public String address() default "";
  35. }

定义了注解,并在需要的时候给相关类,类属性加上注解信息,如果没有响应的注解信息处理流程,注解可以说是没有实用价值。如何让注解真真的发挥作用,主要就在于注解处理方法,下一步我们将学习注解信息的获取和处理!

二、注解的使用:

第一步:新建一个annotation,名字为:MyAnnotation.java。

  1. package com.dragon.test.annotation;
  2.  
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7.  
  8. /**
  9. * Created by gmq on 2015/9/10.
  10. */
  11. @Target(ElementType.METHOD)
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface MyAnnotation
  14. {
  15.  
  16. String hello () default "hello";
  17. String world();
  18. }

第二步:建立一个MyTest.java 来使用上面的annotation。

  1. package com.dragon.test.annotation;
  2.  
  3. /**
  4. * Created by gmq on 2015/9/10.
  5. */
  6. public class MyTest
  7. {
  8.  
  9. @MyAnnotation(hello = "Hello,Beijing",world = "Hello,world")
  10. public void output() {
  11. System.out.println("method output is running ");
  12. }
  13. }

第三步:用反射机制来调用注解中的内容

  1. package com.dragon.test.annotation;
  2.  
  3. import java.lang.annotation.Annotation;
  4. import java.lang.reflect.Method;
  5.  
  6. /**
  7. * 用反射机制来调用注解中的内容
  8. * Created by gmq on 2015/9/10.
  9. */
  10. public class MyReflection
  11. {
  12. public static void main(String[] args) throws Exception
  13. {
  14. // 获得要调用的类
  15. Class<MyTest> myTestClass = MyTest.class;
  16. // 获得要调用的方法,output是要调用的方法名字,new Class[]{}为所需要的参数。空则不是这种
  17. Method method = myTestClass.getMethod("output", new Class[]{});
  18. // 是否有类型为MyAnnotation的注解
  19. if (method.isAnnotationPresent(MyAnnotation.class))
  20. {
  21. // 获得注解
  22. MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
  23. // 调用注解的内容
  24. System.out.println(annotation.hello());
  25. System.out.println(annotation.world());
  26. }
  27. System.out.println("----------------------------------");
  28. // 获得所有注解。必须是runtime类型的
  29. Annotation[] annotations = method.getAnnotations();
  30. for (Annotation annotation : annotations)
  31. {
  32. // 遍历所有注解的名字
  33. System.out.println(annotation.annotationType().getName());
  34. }
  35. }
  36. }

输出:

Hello,Beijing
Hello,world
----------------------------------
com.dragon.test.annotation.MyAnnotation

annotation(@Retention@Target)详解的更多相关文章

  1. springMVC的自定义annotation(@Retention@Target)详解

    自定义注解: 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节.在定义注解时,不能继承其他的注解或接口.@ ...

  2. Java Annotation自定义注解详解

    在开发过程中总能用到注解,但是从来没有自己定义过注解.最近赋闲在家,研究整理了一番,力求知其然知其所以然. 本文会尝试描述什么是注解,以及通过一个Demo来说明如何在程序中自定义注解.Demo没有实际 ...

  3. annotation @Retention@Target

    一.注解:深入理解JAVA注解 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 1.元注解(meta-a ...

  4. Support Annotation Library使用详解

    概述 Support Annotation Library是在Android Support Library19.1版本开始引入的一个全新的函数包,它包含了诸多有用的元注解.用来帮助开发者在编译期间发 ...

  5. Servlet3.0新特性WebFilter(Annotation Filter)详解

    摘要: Servlet3.0作为J2EE 6规范一部分,并随J2EE6一起发布,WeFilter是过滤器注解,是Servlet3.0的新特性,不需要在web.xml进行配置,简化了配置. Name T ...

  6. jquery的2.0.3版本源码系列(4):285-348行,extend方法详解

    目录 1 . jquery extend的基本使用 通过285行的源码 jQuery.extend = jQuery.fn.extend = function() { ,extend方法要么是直接挂在 ...

  7. Java Annotation详解 理解和使用Annotation

    系统中用到了java注解: 查了一下如何使用注解,到底注解是什么: (1)创建方法:MsgTrace Java Class==> 在Create New Class中: name:输入MsgTr ...

  8. Java注解(Annotation)详解

    转: Java注解(Annotation)详解 幻海流心 2018.05.23 15:20 字数 1775 阅读 380评论 0喜欢 1 Java注解(Annotation)详解 1.Annotati ...

  9. Java_注解_01_注解(Annotation)详解

    一.注解的概念 Annotation(注解)是插入代码中的元数据(元数据从metadata一词译来,就是“描述数据的数据”的意思),在JDK5.0及以后版本引入.它可以在编译期使用预编译工具进行处理, ...

随机推荐

  1. Kettle_使用Pan.bat执行转换、Kitchen.bat执行作业

    参考资料:http://www.cnblogs.com/wxjnew/p/3620792.html 注意:使用bat文件执行速度比执行在spoon.bat中执行慢很多 一.使用Pan.bat执行转换 ...

  2. CSS模版收集

    Css Reset by Eric MeyerURL:http://www.ahrefmagazine.com/web-design/30-useful-css-snippets-for-develo ...

  3. __HTML_5读取文件API

    //HTML5 __FileSystemApi <!doctype html> <html> <head> <meta charset="utf-8 ...

  4. Java设计模式-组合模式(Composite)

    组合模式有时又叫部分-整体模式在处理类似树形结构的问题时比较方便,看看关系图: 直接来看代码: public class TreeNode { private String name; private ...

  5. 【poj1745】 Divisibility

    http://poj.org/problem?id=1745 (题目链接) 题意 给出n串数,可以在其两两之间添加+或-,判断是否存在某种方案使得出的表达式的答案可以整除k. Solution 水题一 ...

  6. 点击div区域以外部分,div区域隐藏

    核心思想: 监听body的click事件,事件触发的时候判断是否发生在弹出的div上,如果不在,关闭弹层 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTM ...

  7. POJ3784 Running Median

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1670   Accepted: 823 Description For th ...

  8. jquery中datagrid中getSelected和getSelections的应用

    http://blog.sina.com.cn/s/blog_8e50ede90101fff9.html 刚开始使用jquery的datagrid就知道如果要对特定的一行进行编辑,可以是 $('#on ...

  9. linux(Debian)下安装与MySql的安装、卸载、配置及使用

    参考资料:http://www.cnblogs.com/xusir/p/3334217.html 以下是简要记录. 一.安装 安装:apt-get install mysql-server mysql ...

  10. JavaScript事件

    关于JavaScript事件讲解得很全面的一篇文章:http://www.cnblogs.com/tugenhua0707/p/4501843.html 如下代码需要注意的一点是,除了getEvent ...