Java 5 SE的许多出色功能之一是Annotations构造的引入。
注释是一些标签,我们可以将其插入程序源代码中,以使用某种工具对其进行处理并使其变得有意义。 注释处理工具通常使用(Java 5 SE的)Reflection API在Java代码或字节码级别的源代码级别处理代码,以处理编译器已将注释放入其中的类文件。 Java注释在网络上的许多地方都得到了很好的解释,但唯一能找到一个明智而完整的示例的地方是Prentice Hall出版的一本精装书,名为Core Java:Volume II – Advanced Features,由Cay S. Horstmann撰写。和加里·康奈尔。

网络上几乎所有试图解释注释的地方都缺少为我们展示用于自定义书面注释的注释处理工具(APT)以及从代码中使用注释的最关键部分。 我已使用本书中的信息构建了一些注释,用于验证变量并从项目的属性文件中初始化变量中的值。 我对www上缺少编写自定义Java注释的示例的观察,促使我写这篇文章。 因此,向您提供一个示例自定义Java注释,以帮助您为自己可能要做的事情编写自己的注释。

我将带您遍历NullValueValidate批注,其名称所暗示的目的是验证其注释的变量包含非null值。 如果在处理时发现null值,则将抛出NullPointerException

声明注释

让我们首先声明我们的注释。 该声明将由打算使用注释来注释其对象中变量的代码使用。

package annotation.declaration;
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;/*** Null Value Validate is, as the name suggests an annotation to* validate whether the parameter is null or not* @author         Y.Kamesh Rao**/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)public @interface NullValueValidate {String paramName();
}

注意“ interface”关键字前面的“ @”(AT)符号。 这是用于声明注释的语法。 这称为注释接口 。 界面的方法对应于注释的元素。 paramName() –这是我们的注释声明包含的唯一元素。 它存储带注释的字段的名称,以便在处理时在消息中显示它。 请注意,该声明看起来像一个函数声明。 其实就是这样。 @interface实际上声明了一个Java接口,该接口的实现由使用注释的对象提供。 注释处理器接收使用/实现注释的对象,并调用注释接口方法以检索注释元素。 在我们的例子中, NullValueValidateAnnotationProcessor将接收该类的对象,该类的某些字段使用NullValueValidate注释进行了注释。 然后,该处理器将调用paramName()方法来检索此注释元素的值。

我们使用3种Java提供的注释来注释声明的属性。 这些也可以称为“ 内置注释” ,用于“注释” 。 (嗯,绕口令比这强得多)。 @Documented –表示在使用JavaDocs为此项目创建文档时,必须包含注释声明。 缺省情况下,注释是从使用javadocs命令生成的文档中排除的。 @Target –指示您的Java程序中应对其应用注释的目标元素。 它可以是字段,方法,类或整个包本身。 我们的NullValueValidate注释仅适用于类字段。 这是此枚举可能取的值–

  • TYPE –仅适用于Type。 类型可以是Java类或接口,也可以是Enum甚至是Annotation。
  • FIELD –仅适用于Java字段(在类级别声明的对象,实例或静态)。
  • 方法–仅适用于方法。
  • 参数–仅应用于方法定义中的方法参数。
  • 构造函数–仅适用于类的构造函数。
  • LOCAL_VARIABLE –仅适用于局部变量。 (在方法或代码块中声明的变量)。
  • ANNOTATION_TYPE –仅适用于注释类型。
  • 包装-仅适用于包装。

@Retention –指示用于注释的保留策略。 简单来说,我们将保留注释很长时间。 有三个可能的值–

  • 源–注释将被编译器丢弃。
  • CLASS –注释由编译器记录在类文件中,但VM在运行时无需保留。 这是默认行为。
  • RUNTIME –注释由编译器记录在类文件中,并在运行时由VM保留,因此可以通过反射方式读取它们。

由于我们计划在程序运行时处理批注,因此将RetentionPolicy设置为RUNTIME@Target@Retention也称为元注释。

注释处理工具

注释处理器工具,解析它接收的对象,并在仔细检查对象中找到正在处理的注释时采取编程的措施。 这是我们先前声明的注释的注释处理器– NullValueValidate

package annotation.processor;import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import annotation.declaration.NullValueValidate;/*** The class file to actually carry out the validations* for the various validate annotations we have declared* @author         Y.Kamesh Rao*/
public class NullValueValidateAnnotationProcessor {/*** Method to process all the annotations* @param obj    The name of the object where*               annotations are to be identified and*               processed*/public static void processAnnotations(Object obj) {try {Class cl = obj.getClass();// Checking all the fields for annotationsfor(Field f : cl.getDeclaredFields()) {// Since we are Validating fields, there may be many// NullPointer and similar exceptions thrown,// so we need  to catch themtry {// Processing all the annotations on a single fieldfor(Annotation a : f.getAnnotations()) {// Checking for a NullValueValidate annotationif(a.annotationType() == NullValueValidate.class) {NullValueValidate nullVal = (NullValueValidate) a;System.out.println('Processing the field : '+ nullVal.paramName());// Setting the field to be accessible from our class// is it is a private member of the class under processing// (which its most likely going to be)// The setAccessible method will not work if you have// Java SecurityManager configured and active.f.setAccessible(true);// Checking the field for a null value and// throwing an exception is a null value encountered.// The get(Object obj) method on Field class returns the// value of the Field for the Object which is under test right now.// In other words, we need to send 'obj' as the object// to this method since we are currently processing the// annotations present on the 'obj' Object.if(f.get(obj) == null) {throw new NullPointerException('The value of the field '+f.toString()+' can't be NULL.');} elseSystem.out.println('Value of the Object : '+f.get(obj));}}} catch(Exception e) {System.out.println(e.getMessage());e.printStackTrace();}}} catch(Exception e) {System.out.println(e.getMessage());e.printStackTrace();}}
}

大部分代码是带有注释的自我解释。 请参考该代码以了解详细信息。 基本上,它具有一个称为processAnnotations的静态方法,该方法采用包含需要处理的注释的类的对象。 然后,我们使用Java Reflection API处理此接收到的对象参数中的每个Field,并在字段上找到NullValueValidate注释时采取必要的空值验证操作。 如果找到空值,则抛出NullPointerException或在控制台上打印该值。

注释用法请参考以下代码,该代码使用我们刚刚实现的NullValueValidate注释。 它也使用NullValueValidateAnnotationProcessor在运行时通过从其构造函数调用它在其字段上处理声明的注释。 还要注意,注释的使用方式与变量或字段声明的访问修饰符(如private或public)相似。 通常,输入换行符可以提高代码的可读性。 否则,注释可以很好地与变量/字段声明在同一行中。 注释的名称前面带有“ @”(AT)符号。

package annotation;import annotation.declaration.NullValueValidate;
import annotation.processor.NullValueValidateAnnotationProcessor;/** Main class to test the Annotations  *   @author         Y.Kamesh Rao */
public class AnnotationExample {@NullValueValidate(paramName = 'testVar1') private String testVar1;@NullValueValidate(paramName = 'testVar2') private String testVar2;public AnnotationExample() {testVar2 = 'Testing the Null Value Validation...It Works...!';         // Calling the processor to process the annotations applied         // on this class object.         NullValueValidateAnnotationProcessor.processAnnotations(this);     }     public static void main(String args[]) {AnnotationExample ae = new AnnotationExample();     }
}

输出量

Processing the field:testVar1
Value of the Object:Testing the Null Value Validation...It Works...!
Processing the field:testVar2
The value of the field private java.lang.String annotation.AnnotationExample.testVar2 cannot be NULL.
java.lang.NullPointerException:The value of the field private java.lang.String annotation.AnnotationExample.testVar2 cannot be NULL.at annotation.processor.NullValueValidateAnnotationProcessor.processAnnotation
(NullValueValidateAnnotationProcessor.java:66)at annotation.AnnotationExample.(AnnotationExample.java:28)at annotation.AnnotationExample.main(AnnotationExample.java:33)

结论

我做这个示例注释程序很有趣,现在我实现了许多自定义注释,以从属性文件中加载属性,验证数据库字段长度等。注释极大地减少了代码的冗长性,因此使其更加简单易读。 注释可用于日志记录,生成依赖于代码的部署描述符以及其他机械和重复的作业。 我为你们编写这篇文章带来了很多乐趣。 希望您能从中受益。

参考: Java注释:我们的JCG合作伙伴 Y Kamesh Rao在OrangeApple博客上进行了探索和解释 。

翻译自: https://www.javacodegeeks.com/2012/08/java-annotations-explored-explained.html

Java注释:探究和解释相关推荐

  1. Java注释教程– ULTIMATE指南(PDF下载)

    编者注:在本文中,我们提供了全面的Java注释教程. Java中的注释是一项主要功能,每个Java开发人员都应该知道如何使用它们. 我们在Java Code Geeks上提供了许多教程,例如创建自己的 ...

  2. java注释@para_Java中文档注释各字段的含义是什么?例如author表示作者,para表示参数等...

    匿名用户 1级 2014-12-10 回答 常用Java注释标签(Java comment tags) @author 作者 适用范围:文件.类.方法 (*多个作者使用多个@author标签标识,ja ...

  3. python注释_不建议使用Java注释的正确方法

    python注释 几乎没有什么@Deprecated没有适当的文档看到@Deprecated方法更令人生气的了. 我感到失落. 我应该仍然使用该方法吗? 可能这不是开发人员的意图,这就是为什么他/她添 ...

  4. java注释是用什么标签_java的注释标签是什么?

    java的注释标签是什么? 发布时间:2020-05-23 15:22:41 来源:亿速云 阅读:112 作者:鸽子 注释是一门语言的重要组成成分,比如C语言,HTML语言,PHP语言,他们都有自己的 ...

  5. java注释 param_java注释文档(下)

    原标题:java注释文档(下) 3. 使用 @param.@return 和 @exception 说明方法 这三个标记都是只用于方法的.@param 描述方法的参数,@return 描述方法的返回值 ...

  6. Java注释--单行注释、多行注释、文档注释

    Java注释–单行注释.多行注释.文档注释 单行注释和多行注释 语法格式 //单行注释 //单行注释 //注释内容/* 这里可以放置多行注释 多行注释的内容 Java真的学起来有意思!! */ 举例: ...

  7. java 自定义注释_带有自定义注释的Java注释教程

    java 自定义注释 Java批注提供有关代码的信息,并且它们对其批注的代码没有直接影响. 在本教程中,我们将学习Java注释,如何编写自定义注释 ,注释用法以及如何使用反射来解析注释 . 注释是在J ...

  8. Java注释是一个大错误

    注释是在Java 5中引入的,我们都为之兴奋. 如此出色的工具可以缩短代码! 不再有Hibernate / Spring XML配置文件! 只是注释,就在我们需要它们的代码中. 没有更多的标记接口 , ...

  9. 带有自定义注释的Java注释教程

    Java注释提供有关代码的信息,并且它们对所注释的代码没有直接影响. 在本教程中,我们将学习Java注释,如何编写自定义注释 ,注释用法以及如何使用反射来解析注释 . 注释是在Java 1.5中引入的 ...

最新文章

  1. 2010河北职称计算机考试,2010年河北省职称计算机考试试题..doc
  2. call_user_func() expects parameter 1 to be a valid callback, cannot access private method
  3. hadoop大数据分析与挖掘实战(读书笔记3)
  4. 怎么优化GO语言服务的内存占用
  5. python EasyGui
  6. 关于WCF、WebAPI、WCFREST、WebService之间的区别总结
  7. SQL Server数学函数
  8. mysql 常用字符串操作
  9. bootstrap时间格式化
  10. maven 命令_Maven企业实战系列(二):Maven高效率初体验
  11. 【Java】多线程编程
  12. LevelDB源码之五Current文件\Manifest文件\版本信息
  13. 初入laravel之坑
  14. 建模与计算机应用,数学建模与计算机应用竞赛.doc
  15. vue项目富文本编辑器输入格式化以计算总字数
  16. 第10章结构体01——结构体字节大小的计算
  17. 云ERP来的正是时候!
  18. Python代码太长换行
  19. 移动页面滚动穿透解决方案(荐)
  20. 空压机远程监测及控制系统

热门文章

  1. HttpClient api-连接池
  2. java原始类型和引用类型_Java中的8种原始类型
  3. java 和javafx_Java,JavaFX的流利设计风格文本字段和密码字段
  4. flowable背压 取消_使用Flowable.generate()生成可感知背压的流– RxJava常见问题解答...
  5. couchbase_适用于具有Couchbase和WildFly的多容器和多主机应用程序的Docker Machine,Swarm和Compose...
  6. netflix测试能不能看_Netflix监管者测试–引入知事,准官员
  7. apache hadoop_使用Apache Hadoop计算PageRanks
  8. aop 获取注解注释的方法_带有AOP和注释的Java方法记录
  9. html嵌入war_WAR文件与具有嵌入式服务器的Java应用程序
  10. Java 12新功能完整指南