您的位置 首页 > 德语词汇

annotate是什么意思(深入理解Java注解类型)

今天给各位分享annotate是什么意思的知识,其中也会对深入理解Java注解类型进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

annotate是什么意思(深入理解Java注解类型)

来源:https://www.cnblogs.com/java-chen-hao/p/11024153.html

Anannotationisaformofmetadata,thatcanbeaddedtoJavasourcecode.Classes,methods,variables,parametersandpackagesmaybeannotated.Annotationshavenodirecteffectontheoperationofthecodetheyannotate.

注解是一种能被添加到java代码中的元数据,类、方法、变量、参数和包都可以用注解来修饰。注解对于它所修饰的代码并没有直接的影响。

注解是一种元数据形式。即注解是属于java的一种数据类型,和类、接口、数组、枚举类似。注解用来修饰,类、方法、变量、参数、包。注解不会对所修饰的代码产生直接的影响。

继续看看官方对它的使用范围的描述:

Annotationshaveanumberofuses,amongthem:Informationforthecomplier-Annotationscanbeusedbythecompilertodetecterrorsorsuppresswarnings.Compiler-timeanddeployment-timeprocessing-Softwaretoolscanprocessannotationinformationtogeneratecode,XMLfiles,andsoforth.Runtimeprocessing-Someannotationsareavailabletobeexaminedatruntime.

注解又许多用法,其中有:为编译器提供信息-注解能被编译器检测到错误或抑制警告。编译时和部署时的处理-软件工具能处理注解信息从而生成代码,XML文件等等。运行时的处理-有些注解在运行时能被检测到。

##2如何自定义注解基于上一节,已对注解有了一个基本的认识:注解其实就是一种标记,可以在程序代码中的关键节点(类、方法、变量、参数、包)上打上这些标记,然后程序在编译时或运行时可以检测到这些标记从而执行一些特殊操作。因此可以得出自定义注解使用的基本流程:

第一步,定义注解——相当于定义标记;第二步,配置注解——把标记打在需要用到的程序代码中;第三步,解析注解——在编译期或运行时检测到标记,并进行特殊操作。

注解在Java中,与类、接口、枚举类似,因此其声明语法基本一致,只是所使用的关键字有所不同@interface。在底层实现上,所有定义的注解都会自动继承java.lang.annotation.Annotation接口。

public@interfaceCherryAnnotation{\n\n}

注解类型的实现部分:

根据我们在自定义类的经验,在类的实现部分无非就是书写构造、属性或方法。但是,在自定义注解中,其实现部分只能定义一个东西:注解类型元素(annotationtypeelement)。咱们来看看其语法:

public@interfaceCherryAnnotation{\npublicStringname();\nintage()default18;\nint[]array();\n}

定义注解类型元素时需要注意如下几点:

一个最最基本的注解定义就只包括了上面的两部分内容:1、注解的名字;2、注解包含的类型元素。但是,我们在使用JDK自带注解的时候发现,有些注解只能写在方法上面(比如@Override);有些却可以写在类的上面(比如@Deprecated)。当然除此以外还有很多细节性的定义,那么这些定义该如何做呢?接下来就该元注解出场了!元注解:专门修饰注解的注解。它们都是为了更好的设计自定义注解的细节而专门设计的。我们为大家一个个来做介绍。

@Target注解,是专门用来限定某个自定义注解能够被应用在哪些Java元素上面的。它使用一个枚举类型定义如下:

publicenumElementType{\n/**类,接口(包括注解类型)或枚举的声明*/\nTYPE,\n\n/**属性的声明*/\nFIELD,\n\n/**方法的声明*/\nMETHOD,\n\n/**方法形式参数声明*/\nPARAMETER,\n\n/**构造方法的声明*/\nCONSTRUCTOR,\n\n/**局部变量声明*/\nLOCAL_VARIABLE,\n\n/**注解类型声明*/\nANNOTATION_TYPE,\n\n/**包的声明*/\nPACKAGE\n}

//@CherryAnnotation被限定只能使用在类、接口或方法上面\n@Target(value={ElementType.TYPE,ElementType.METHOD})\npublic@interfaceCherryAnnotation{\nStringname();\nintage()default18;\nint[]array();\n}@Retention

@Retention注解,翻译为持久力、保持力。即用来修饰自定义注解的生命力。注解的生命周期有三个阶段:1、Java源文件阶段;2、编译到class文件阶段;3、运行期阶段。同样使用了RetentionPolicy枚举类型定义了三个阶段:

publicenumRetentionPolicy{\n/**\n*Annotationsaretobediscardedbythecompiler.\n*(注解将被编译器忽略掉)\n*/\nSOURCE,\n\n/**\n*Annotationsaretoberecordedintheclassfilebythecompiler\n*butneednotberetainedbytheVMatruntime.Thisisthedefault\n*behavior.\n*(注解将被编译器记录在class文件中,但在运行时不会被虚拟机保留,这是一个默认的行为)\n*/\nCLASS,\n\n/**\n*Annotationsaretoberecordedintheclassfilebythecompilerand\n*retainedbytheVMatruntime,sotheymaybereadreflectively.\n*(注解将被编译器记录在class文件中,而且在运行时会被虚拟机保留,因此它们能通过反射被读取到)\n*@seejava.lang.reflect.AnnotatedElement\n*/\nRUNTIME\n}

我们再详解一下:

@Retention(RetentionPolicy.RUNTIME)\n@Target(value={ElementType.METHOD})\n@Documented\npublic@interfaceCherryAnnotation{\nStringname();\nintage()default18;\nint[]score();\n}

publicclassStudent{\n@CherryAnnotation(name="cherry-peng",age=23,score={99,66,77})\npublicvoidstudy(inttimes){\nfor(inti=0;i<times;i++){\nSystem.out.println("GoodGoodStudy,DayDayUp!");\n}\n}\n}

简单分析下:

为了运行时能准确获取到注解的相关信息,Java在java.lang.reflect反射包下新增了AnnotatedElement接口,它主要用于表示目前正在VM中运行的程序中已使用注解的元素,通过该接口提供的方法可以利用反射技术地读取注解的信息,如反射包的Constructor类、Field类、Method类、Package类和Class类都实现了AnnotatedElement接口,它简要含义如下:

Constructor:代表类的构造器定义

下面是AnnotatedElement中相关的API方法,以上5个类都实现以下的方法

@Documented\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceDocumentA{\n}

packagecom.zejian.annotationdemo;\n\nimportjava.lang.annotation.Annotation;\nimportjava.util.Arrays;\n\n@DocumentA\nclassA{\n\n}\n\n//继承了A类\n@DocumentB\npublicclassDocumentDemoextendsA{\n\npublicstaticvoidmain(String...args){\n\nClass<?>clazz=DocumentDemo.class;\n//根据指定注解类型获取该注解\nDocumentAdocumentA=clazz.getAnnotation(DocumentA.class);\nSystem.out.println("A:"+documentA);\n\n//获取该元素上的所有注解,包含从父类继承\nAnnotation[]an=clazz.getAnnotations();\nSystem.out.println("an:"+Arrays.toString(an));\n//获取该元素上的所有注解,但不包含继承!\nAnnotation[]an2=clazz.getDeclaredAnnotations();\nSystem.out.println("an2:"+Arrays.toString(an2));\n\n//判断注解DocumentA是否在该元素上\nbooleanb=clazz.isAnnotationPresent(DocumentA.class);\nSystem.out.println("b:"+b);\n\n}\n}

执行结果:

A:@com.zejian.annotationdemo.DocumentA()\nan:[@com.zejian.annotationdemo.DocumentA(),@com.zejian.annotationdemo.DocumentB()]\nan2:@com.zejian.annotationdemo.DocumentB()\nb:true

通过反射获取上面我们自定义注解

publicclassTestAnnotation{\npublicstaticvoidmain(String[]args){\ntry{\n//获取Student的Class对象\nClassstuClass=Class.forName("pojos.Student");\n\n//说明一下,这里形参不能写成Integer.class,应写为int.class\nMethodstuMethod=stuClass.getMethod("study",int.class);\n\nif(stuMethod.isAnnotationPresent(CherryAnnotation.class)){\nSystem.out.println("Student类上配置了CherryAnnotation注解!");\n//获取该元素上指定类型的注解\nCherryAnnotationcherryAnnotation=stuMethod.getAnnotation(CherryAnnotation.class);\nSystem.out.println("name:"+cherryAnnotation.name()+",age:"+cherryAnnotation.age()\n+",score:"+cherryAnnotation.score()[0]);\n}else{\nSystem.out.println("Student类上没有配置CherryAnnotation注解!");\n}\n}catch(ClassNotFoundExceptione){\ne.printStackTrace();\n}catch(NoSuchMethodExceptione){\ne.printStackTrace();\n}\n}\n}运行时注解处理器

了解完注解与反射的相关API后,现在通过一个实例(该例子是博主改编自《TinkinginJava》)来演示利用运行时注解来组装数据库SQL的构建语句的过程

/**\n*CreatedbyChenHaoon2019/6/14.\n*表注解\n*/\n@Target(ElementType.TYPE)//只能应用于类上\n@Retention(RetentionPolicy.RUNTIME)//保存到运行时\npublic@interfaceDBTable{\nStringname()default"";\n}\n\n\n/**\n*CreatedbyChenHaoon2019/6/14.\n*注解Integer类型的字段\n*/\n@Target(ElementType.FIELD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceSQLInteger{\n//该字段对应数据库表列名\nStringname()default"";\n//嵌套注解\nConstraintsconstraint()default@Constraints;\n}\n\n\n/**\n*CreatedbyChenHaoon2019/6/14.\n*注解String类型的字段\n*/\n@Target(ElementType.FIELD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceSQLString{\n\n//对应数据库表的列名\nStringname()default"";\n\n//列类型分配的长度,如varchar(30)的30\nintvalue()default0;\n\nConstraintsconstraint()default@Constraints;\n}\n\n\n/**\n*CreatedbyChenHaoon2019/6/14.\n*约束注解\n*/\n\n@Target(ElementType.FIELD)//只能应用在字段上\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceConstraints{\n//判断是否作为主键约束\nbooleanprimaryKey()defaultfalse;\n//判断是否允许为null\nbooleanallowNull()defaultfalse;\n//判断是否唯一\nbooleanunique()defaultfalse;\n}\n\n/**\n*CreatedbyChenHaoon2019/6/14.\n*数据库表Member对应实例类bean\n*/\n@DBTable(name="MEMBER")\npublicclassMember{\n//主键ID\n@SQLString(name="ID",value=50,constraint=@Constraints(primaryKey=true))\nprivateStringid;\n\n@SQLString(name="NAME",value=30)\nprivateStringname;\n\n@SQLInteger(name="AGE")\nprivateintage;\n\n@SQLString(name="DESCRIPTION",value=150,constraint=@Constraints(allowNull=true))\nprivateStringdescription;//个人描述\n\n//省略setget.....\n}

上述定义4个注解,分别是@DBTable(用于类上)、@Constraints(用于字段上)、@SQLString(用于字段上)、@SQLString(用于字段上)并在Member类中使用这些注解,这些注解的作用的是用于帮助注解处理器生成创建数据库表MEMBER的构建语句,在这里有点需要注意的是,我们使用了嵌套注解@Constraints,该注解主要用于判断字段是否为null或者字段是否唯一。必须清楚认识到上述提供的注解生命周期必须为@Retention(RetentionPolicy.RUNTIME),即运行时,这样才可以使用反射机制获取其信息。有了上述注解和使用,剩余的就是编写上述的注解处理器了,前面我们聊了很多注解,其处理器要么是Java自身已提供、要么是框架已提供的,我们自己都没有涉及到注解处理器的编写,但上述定义处理SQL的注解,其处理器必须由我们自己编写了,如下

packagecom.chenHao.annotationdemo;\nimportjava.lang.annotation.Annotation;\nimportjava.lang.reflect.Field;\nimportjava.util.ArrayList;\nimportjava.util.List;\n\n/**\n*Createdbychenhaoon2019/6/14.\n*运行时注解处理器,构造表创建语句\n*/\npublicclassTableCreator{\n\npublicstaticStringcreateTableSql(StringclassName)throwsClassNotFoundException{\nClass<?>cl=Class.forName(className);\nDBTabledbTable=cl.getAnnotation(DBTable.class);\n//如果没有表注解,直接返回\nif(dbTable==null){\nSystem.out.println(\n"NoDBTableannotationsinclass"+className);\nreturnnull;\n}\nStringtableName=dbTable.name();\n//Ifthenameisempty,usetheClassname:\nif(tableName.length()<1)\ntableName=cl.getName().toUpperCase();\nList<String>columnDefs=newArrayList<String>();\n//通过Class类API获取到所有成员字段\nfor(Fieldfield:cl.getDeclaredFields()){\nStringcolumnName=null;\n//获取字段上的注解\nAnnotation[]anns=field.getDeclaredAnnotations();\nif(anns.length<1)\ncontinue;//Notadbtablecolumn\n\n//判断注解类型\nif(anns[0]instanceofSQLInteger){\nSQLIntegersInt=(SQLInteger)anns[0];\n//获取字段对应列名称,如果没有就是使用字段名称替代\nif(sInt.name().length()<1)\ncolumnName=field.getName().toUpperCase();\nelse\ncolumnName=sInt.name();\n//构建语句\ncolumnDefs.add(columnName+"INT"+\ngetConstraints(sInt.constraint()));\n}\n//判断String类型\nif(anns[0]instanceofSQLString){\nSQLStringsString=(SQLString)anns[0];\n//Usefieldnameifnamenotspecified.\nif(sString.name().length()<1)\ncolumnName=field.getName().toUpperCase();\nelse\ncolumnName=sString.name();\ncolumnDefs.add(columnName+"VARCHAR("+\nsString.value()+")"+\ngetConstraints(sString.constraint()));\n}\n\n\n}\n//数据库表构建语句\nStringBuildercreateCommand=newStringBuilder(\n"CREATETABLE"+tableName+"(");\nfor(StringcolumnDef:columnDefs)\ncreateCommand.append("\\n"+columnDef+",");\n\n//Removetrailingcomma\nStringtableCreate=createCommand.substring(\n0,createCommand.length()-1)+");";\nreturntableCreate;\n}\n\n\n/**\n*判断该字段是否有其他约束\n*@paramcon\n*@return\n*/\nprivatestaticStringgetConstraints(Constraintscon){\nStringconstraints="";\nif(!con.allowNull())\nconstraints+="NOTNULL";\nif(con.primaryKey())\nconstraints+="PRIMARYKEY";\nif(con.unique())\nconstraints+="UNIQUE";\nreturnconstraints;\n}\n\npublicstaticvoidmain(String[]args)throwsException{\nString[]arg={"com.zejian.annotationdemo.Member"};\nfor(StringclassName:arg){\nSystem.out.println("TableCreationSQLfor"+\nclassName+"is:\\n"+createTableSql(className));\n}\n}\n}

输出结果:

TableCreationSQLforcom.zejian.annotationdemo.Memberis:\nCREATETABLEMEMBER(\nIDVARCHAR(50)NOTNULLPRIMARYKEY,\nNAMEVARCHAR(30)NOTNULL,\nAGEINTNOTNULL,\nDESCRIPTIONVARCHAR(150)\n);

如果对反射比较熟悉的同学,上述代码就相对简单了,我们通过传递Member的全路径后通过Class.forName()方法获取到Member的class对象,然后利用Class对象中的方法获取所有成员字段Field,最后利用field.getDeclaredAnnotations()遍历每个Field上的注解再通过注解的类型判断来构建建表的SQL语句。这便是利用注解结合反射来构建SQL语句的简单的处理器模型。

annotate是什么意思和深入理解Java注解类型的问题分享结束啦,以上的文章解决了您的问题吗?欢迎您下次再来哦!

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023