Java注释:探究和解释

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371456.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 类

一 string 类型 变量.Length - 字符串长度,返回int类型 string s "abcdefg"; int a s . Length; Console.WriteLine(a); // 输出结果为:7(此字符串有7个字符) // Length返回有多少个字符&am…

node+mongodb+win7

一、安装mongodb,参照教程,注意要先启动mongod.exe,再启动mongd.exe。 转载于:https://www.cnblogs.com/iloveyou-sky/p/7396997.html

cdrom是多媒体微型计算机,全国计算机二级题库第三章

同时按下CTRLALTDEL组合键的作用是(使用任务管理器关闭不响应的应用程序下列说法正确的是(在微型机性能指标中,CPU的主频越离,其运算速度越快)微型计算机键盘上的Tab键是(交替换档键)微型计算机键盘上的Enter键是(回车键)微型计算机的运行速度的单位是mi…

Spring MVC控制器JUnit测试

JUnit测试Spring MVC控制器并非易事 。 但是最近,一个新项目 (即将在Spring推出)提供了新工具来简化此工作。 这篇文章说明了如何通过JUnit测试来测试一个简单的控制器。 该代码是JUnit Testing Spring Service和DAO(带有内存数据…

java基础03变量和基本数据类型

package cn.bdqn.test;/*** * author 小豆腐* * 变量:会变化的量??* 一个数据在内存中存储空间的表示!在运行期间可以动态改变!* * 关键字:在java中已经被使用或者定义的单词!不能作为变量名&#xff01…

5.set集合

list_1 [1,2,3,4,5]list_2 [1,3,5,7,9]#列表转成set集合set_1 set(list_1)set_2 set(list_2)#交集print(set_1.intersection(set_2))print(set_1 & set_2)#判断没有交集print(set(["a","b"]).isdisjoint(set_1))#并集print(set_1.union(set_2))pri…

JavaFX中基于表达式的PathTransitions

在JavaFX中,您可以使用PathTransition对象为路径上的节点设置动画。 PathTransitions使用Shape对象描述它们需要沿其动画的路径。 JavaFX提供了各种类型的形状(例如,多边形,圆形,多边形,路径)。…

html 显示视频列表,dvd光碟制作节目轨菜单布局,不要视频缩略图,只显示文件列表...

“如何在刻录视频光盘时自定义制作菜单?实现的效果就是当光盘插入DVD影碟机播放时,首先会出现一个所有视频文件列表的菜单(节目轨菜单),就相似于音乐CD曲目表一样,不需要有视频缩略图,可通过遥控器选择性播放列表中某一…

v3学院教你学习-task和function的异同

v3学院教你学习-task和function的异同 task(任务)与function(函数)的不同 任务与函数主要有以下四点不同: l 函数只能与主模块共用一个仿真时间单位,而任务定义自己的仿真时间单位。 l 函数不能启动任务&am…

Spring事件的观察者模式

介绍 观察者模式的本质是“定义对象之间的一对多依赖关系,以便当一个对象改变状态时,其所有依赖关系都会得到通知并自动更新。” GoF。 观察者模式是发布/订阅模式的子集,它允许许多观察者对象查看事件。 可以在不同的情况下使用此模式&#…

jQuery选择什么版本 1.x? 2.x? 3.x?

目前jQuery有三个大版本: 1.x:兼容ie678,使用最为广泛的,官方只做BUG维护,功能不再新增。因此一般项目来说,使用1.x版本就可以了,最终版本:1.12.4 (2016年5月20日)2.x:不兼容ie678&a…

Delta DVP 系列 PLC 各装置 Modbus 地址

此Modbus地址表以 1 为基础地址 Device Range Type DVP address (Hex) Modbus address (Dec) Effective ES/EX/SS SA/SX/SC EH S 000~255 bit 0000~00FF 000001~000256 0~127 0~1024 0~1024 S 256~511 bit 0100~01FF 000247~000512 S 512~767 bit 020…

Reporting Service 2008 “报表服务器数据库内出错。此错误可能是因连接失败、超时或数据库中磁盘空间不足而导致的”...

今天遇到了两个关于Reporting Service的问题, 出现问题的环境为Microsoft SQL Server 2008 R2 (SP2) - 10.50.4000.0 (X64) 。具体情况请见下面描述。 1:在修改报表的订阅后,保存时出现下面错误: 提示:报表服务器数据库…

Java 7:HashMap与ConcurrentHashMap

从我过去有关性能的文章和HashMap案例研究中可能已经看到,Java线程安全性问题可以很轻松地使Java EE应用程序和Java EE容器崩溃。 在对Java EE性能问题进行故障排除时,我观察到的最常见问题之一是由非线程安全的HashMap get()和pu…

计算机网络按信息传输介质的性能来划分,大学计算机基础练习题网络技术.doc...

网络技术一、单选:1. 在计算机网络中,表征数据传输可靠性的指标是( )。A?误码率 B?频带利用率C?信道容量 D?传输速率参考答案:A2. 和通信网络相比,计算机网络最本质的功能是( )。A?数据通信 B?资源共享C?提高计算机的可靠性…

【2017-03-02】集合、结构体、枚举

集合和数组的差别: 数组:同一类型,固定长度集合:不同类型,不固定长度 一、普通集合(弱类型) 1、ArryList 使用集合首先要引用命名空间。 或者在ArryList上右键找“解析”。 2、集合的定义&#…

Hibernate懒/急加载示例

这篇文章将重点讨论为什么以及如何在应用程序中使用称为LAZY和EAGER加载的概念,以及如何使用Spring的休眠模板以EAGER方式加载LAZY实体。 当然,正如标题本身所暗示的那样,我们将通过一个示例来说明这一点。 场景就是这样; 您是一…

读者使用计算机终端是指,全国2010年10月自学考试管理系统中计算机应用真题及答案...

A.上级模块向下级模块传递控制信号B.下级模块对上级模块传递控制信号C.同级模块之间传递数据或控制信号D.上级模块向下级模块传递数据信号18.“客户”数据表结构为:客户编号、手机号、购物金额,合理的字段类型为( )A.字符型,字符型&#xff0…

软件测试HW02-------fault error failure

程序一 问题一:i应该>0; 问题二: x为空 问题三:test x[2, 3, 5]; y 3;问题四:test: x[2]; y 3;程序二问题一:循环应该反过来;问题二:无;问题三:test:x[1];问题四:test: x[1,2,3…

Mathematica图片局部变色

这篇博客来源于Stack-Exchange上的一个帖子,问题描述如下:如何将图中的红球变为蓝球? 这个问题下面有很多答案,我选了最好的一个答案,代码如下 img Import["C:/Users/1/Desktop/red.jpg"]; getReds[x_Image…